Breaking changes

As a company operating on the intersection of productivity and dev tools, ensuring our API is a joy to work with is paramount. Over the past couple of weeks, we've been going through all our API endpoints and schemas with a fine toothpick, ensuring they behave in a predictable way and that things are named consistently. Now, before our API is being used by lots of 3rd parties, is the perfect time to do any final large breaking changes.

In parallel, the team has been hard at work building the next iteration of our core advisor workflow, which we'll dive into very soon. Stay tuned!

Across both CoreAPI and CustomerAPI

  • Renamed the timeline query from timeline to timelineEntries. This change makes sense as the return type of timeline was TimelineEntry connection which didn't make too much sense. Now the query name aligns closely with the return type as well as leaving open the possibility for us to add a timeline entity and query if we ever have some metadata about the timeline itself.
  • Removed timelineEntry.createdAt as we decided this was internal implementation detail that we can expose later if needed. Timeline entries have a timestamp field that should be used to determine where an entry should be in a timeline.
  • Renamed internalCustomerId to externalId. Naming is hard. Initially we thought internalCustomerId makes more sense as it's a customer id that's internal to the company that's integrating with us. But after speaking about this and reading our API, we decided it makes more sense to call this an externalId as it's an id that's external to our system / API. We also dropped customer from the name as it's implied by being on the Customer type.
  • Now returning the actor for author fields such as createdBy, updatedBy and deletedBy. This is for consistency to use Actor or InternalActor wherever possible.
    • Moved User.createdBy and User.updatedBy to use InternalActor


  • Renamed our createChat endpoint to sendChat so it's now consistent with the CustomerAPI.
  • Aligned the naming convention of our isAssignedTo filter to isAssigned, we think for boolean properties just having isAssigned makes more sense than isAssignedTo as the later seems to be incomplete ( assigned to .... what?)
  • Renamed workspaceUser to user , workspaceUsers to users , and createUser to createUserAccount. These changes just cleaned up our user and user account setup to align with the following conventions: user ⇒ inside a workspace, userAccount ⇒ outside a workspace (e.g. you haven't created one yet or haven't joined one yet). The majority of the time API users will need to use user so we kept that one the shorter/simpler one.
  • Deleted myPermissions query. We initially thought users would need to fetch a flattened list of their permissions, but it turned out to be more useful if users had roles that returned their permissions.
  • Removed cursor from our backend subscriptions. Initially when implementing subscriptions we were thinking that it would be useful to return a "mega cursor", i.e. a cursor that was able to be used in other list operations to page back and forth. But after thinking through the edge-cases and complexities of this solution (e.g. various filter combinations) we decided to remove it and keep cursors only on list queries paging results.
  • Removed Subscription.customer for a single customer as it is not currently used in the support app. We can easily readd this subscription in the future, but for now since it's not used and the customerChanges subscription already handles this use-case.
  • Renamed Customer.assignedTo to Customer.assignedToUser. Right now Customers can only be assigned to users and not to customers or systems, so we made this domain limitation explicit in the name.
  • Changed Customer.timelineInfo to Customer.timelineInfo!. This was a tiny oversight from our part where timelineInfo was optional on the Customer type when in practice a Customer will always have a timelineInfo.

Customer API

  • Added SystemActor to the Actor union to allow for forward compatibility. As a reminder the SystemActor is an actor that's internal to Plain. This can be something like a migration job or Plain sending a system chat message. Initially we thought that actions from systems wouldn't ever appear on our Customer API, but after thinking about it, some time in the near future this would definitely happen so we should just add it to the union now so it's not a breaking change later.

Other improvements and bugfixes

  • You can now update your workspace details in the support app
  • The plain text versions of our transactional emails now mirror the content of the HTML versions. We focused initially on the HTML part of our emails as that's what the majority of the users see, but now we've fixed the email content for plain text as well!
  • Fixed an issue where the support app would throw sporadic 401s and 403s after being idle for some time
  • Fixed a bug where the advisor assignment modal didn't close after unassignment.
  • #changelog
© Plain. CS without the BS since 2020.