Building an API for Middle
Learn how to develop an API that fits with Middle
API stands for application programming interface. APIs allow for external apps to interact with your app. While Middle can handle other ways to pass data, such as direct database connections and file transfer protocols, using an API is the most secure and dynamic way for Middle to interact with another system. While Middle is flexible, there are ideal conditions that make an API ideal for Middle to connect with.

Authentication

Every endpoint in your API should require authentication. You need to have an authentication scheme that allows Middle to store a key or credentials that it will use to authenticate requests. We recommend OAuth 2's "Authorization Code" grant type. If an OAuth grant flow is too complicated, you can also use a simple "shared secret," such as an API key that can be entered into Middle. Middle would then use this key with every query.
A way to identify who is using your API is important. This type of functionality is built into OAuth, but if you're using a custom authentication solution, you might want an additional key to identify who is making the calls to your API.

Querying for data

When your app is connected to Middle, Middle will begin polling for data. Middle then stores data returned by these syncs. Records have foreign keys to other record types, like the location at which a synced event occurred and the user who completed the event. Middle will store these related records too. If Middle encounters an event with a foreign key it hasn't seen before, Middle will hit your API to get that data.

Accommodating different sync types

Middle is able to query for data in one of three ways: complete transfers, primary key lookups, and recent record poll syncs. Data returned by these syncs are then stored in Middle for workflows to handle. Your API will need to be set up to accommodate syncs like these.

Complete transfers

Complete transfers are good for small data sets where the records do not change often, such as store locations. Complete transfers are best accommodated by an endpoint that allows the developed to list all of the data in a resource.

Primary key lookups

Primary key lookups are good for when you need supplementary data to a record, such as the client who made a purchase. An endpoint in this case should provide the developer with the ability to query all clients in your system by the client's primary user ID.

Recent record poll syncs

Recent record poll syncs grab data as it is updated and created. They generally look at a datetime, like the last modified date, to grab data that has changed over a defined period of time, such as the last 20 minutes. Recent record poll syncs are extremely important in powering a successful Middle app and any relevant endpoint should be set up with datetime range filters.
Please note that a datetime filter that allows a developer to grab records by a created datetime can be problematic. Created datetime filters allow the developer to only grab newly created records and any updates that are made to the record would likely be missed.

Responses

When Middle makes an API call to your app, any records that meet the query criteria should include a response that contains all data relevant to that record type. Middle is then able to take that response, store it, and use that data in workflows. Responses should be UTF-8 encoded. All datetimes in the response data should be in ISO 8601 format with a UTC offset.
Below is the kind of data we would expect to see associated with a user record:
  • User ID (Primary Key)
  • Email
  • First Name
  • Last Name
  • Phone Number
  • Record Last Modified Datetime
  • Any other personal information
Below is an example of the data Middle might get for a location:
  • Location ID (Primary Key)
  • Location Name
  • Street Address
  • City
  • State
  • Zip Code
  • Timezone
  • Record Last Modified Datetime

Pushing to your API

Along with querying for data via an API, Middle can also push to an API performing POST, PUT, or PATCH calls, to name a few. API calls that trigger events or push data to your app are contained within workflow actions. When building an endpoint to perform an action in your app consider what inputs should be included in the API call from the external system and what response you should send back to the external system.

Input

In a case where Middle is performing an action to update or create a user record, an input will be constructed for the action so that the Middle user can define the values they want the user to be updated or created with. This input typically reflects the parameters an endpoint is set up to ingest. Such an endpoint would likely include input parameters like the user's personal information, but also other useful attributes to your app. The same goes for other circumstances, such as triggering a transactional email. An endpoint that triggers an email would likely have an input that included which email template should be used and the email address it should be sent to.

External IDs

When creating and updating users in your app, using external data, it can be difficult to know that an individual in your app is the same individual in another app. Short of cross-referencing the individuals name, email, date of birth, etc., we highly suggest accommodating an external ID that can be passed in from the foreign system to your app. That way, should that user's info be updated and Middle tries to pass over these updates the external ID being passed in will map to the right person and not create a duplicate of the same user. External IDs can be especially useful when mapping locations between apps and other record types that exist in both systems.

Unique Transaction IDs

For endpoints that complete tasks such as sending emails, giving credits or money, awarding points, etc., it's important not to perform duplicate actions as this can have a real-world consequences, such as sending someone the same email twice or giving someone too many credits. The endpoints and workflows performing these actions should be set up to be idempotent when an operation can be applied many times without changing the result. A great solution to provide idempotency is unique transaction IDs. When an endpoint provides a unique transaction ID in the request the app will any API calls that use the same ID more than once. That way if a user is only supposed to be sent an email once per month, should Middle try to send that email again the same month, your app will reject the API call and not send a duplicate email. Such a unique transaction ID might look something like this:
MONTHLY_MEMBER_EMAIL:{current_month}:{current_year}:{user_email}

Output

All API call responses generally include a status of whether or not the call was successful or if it failed. If the call failed an error indicating why it failed should be included. This information is important for troubleshooting actions performed by Middle workflows.
In addition to a call's status, data returned by a call can then be turned around and included in the Middle action output to be referenced later on in a workflow. If an action is creating a user, it might be useful to include information such as the user ID for the newly created user in the response of the API call. You will want to consider what information internal to your system might be useful for developers in Middle to have after an action is performed.