The API lives at https://demoapi.machinelabs.com/v1/ . It’s a graphQL API – see https://graphql.org/learn/ for an overview of how that works. Basically you’ll be POSTing a JSON query to the API URL, and getting a JSON response.
You should have been given an API key when you signed up – you’ll need this for all requests.
To get a full list of available queries, mutations, and types, visit https://demoapi.machinelabs.com/v1/ and look at the Docs panel on the right hand side. The documentation below provides general information on how all of these mutations work, which you can combine with the graphQL documentation above to get the signature for any specific query or mutation.
Authentication
Each request you make to the GraphQL endpoint will need to include an X-Machinelabs-Api-Key
header with the value set to your API key. Each API keys is specific to a single brand so if you have multiple brands then you will need to store a unique key for each. If you lose your API key or it is compromised then please contact support immediately and we can invalidate it and create a new one for you.
Uploading data
You’ll probably want to upload historical data, such as contacts and orders, and then regularly upload any new data, or update any data that has changed.
The main pieces of data you’ll want to upload to use machine labs are contacts, products, and orders. You might also want to upload custom mailing lists (see ‘Mailing lists’ below for the default ones we provide), checkouts (for checkout abandonment automations), refunds (for reporting), product collections (for segmenting by collection), custom merge fields (for adding extra data to contacts), if you want to use any of those features.
There are graphQL mutations for each type of data, which all work the same way. For example, to upload mailing lists, you’d use this mutation:
mutation uploadMailingLists($mailingLists: [MailingListInput]!) { uploadMailingLists(mailingLists: $mailingLists) { result { yourId machineLabsId } errors { message path extensions { affectedIds { yourId machineLabsId } } } } }
and could use these variables:
{ "mailingLists": [{ "yourId": "mailingList1", "name": "My mailing list", "description": "A mailing list", }], }
The response will look something like this:
{ "data": { "uploadMailingLists": { "result": [ { "yourId": "mailingList1", "machineLabsId": "fb9acacf85b645d9a679fd5032542406" } ], "errors": null } } }
The result
key provides the machineLabsId
we’ve assigned to each object you uploaded, matched to yourId
(the identifier you gave when you uploaded it). You need to store the machineLabsId
, as you’ll need it to update the object in future.
To update that object in future (for example here to change the description), include it in an uploadMailingLists
call as above, but including the machineLabsId
from your initial upload of the object so we know you’re updating an object instead of creating it. You can have a mixture of new and updated objects in a single upload batch.
{ "mailingLists": [{ "yourId": "mailingList1", "machineLabsId": "the machineLabsId you obtained above", "name": "My mailing list", "description": "A new description", }], }
Errors
If the data you supplied is in some way invalid, you’ll get a response like:
{ "data": { "uploadMailingLists": { "result": null, "errors": [ { "message": "The following machineLabsId values aren't recognised, please create these interests with uploadMailingLists - fb9acacf85b645d9a679fd5032542407" "path": ["contacts", "machineLabsId"], "extensions": { "affectedIds": [{ "yourId": null, "machineLabsId": "fb9acacf85b645d9a679fd5032542407" ]} }, } ] } } }
with a message that should explain what needs fixed, and an optional path to the field in the source data that caused the issue.
If the error can be attributed to a specific object, either the yourId
or machineLabsId
for that object (or both) will be provided. Which of these are filled out will depend on what data you’ve provided and what information we have available when the error happens. Unexpected errors, or general errors that we haven’t tied to a specific object, won’t have affectedIds
set.
No data will be imported for a batch until all errors are fixed.
If we encounter an internal error of some kind, the data will again not be imported, and you’ll get a response like:
{ "errors": [ { "message": "An error occurred", } ], "data": { "uploadMailingLists": null } }
which won’t have any extra data attached.
Related data
Some data depends on other data. For example, when uploading refunds with uploadRefunds
, each refund requires an orderId
. You’ll need to first upload the order with uploadOrders
, and store the machineLabsId
you get back so you can provide it in uploadRefunds
.
Some objects include other objects, for example the orders provided to uploadOrders
include a list of order_items
. If you provide a new list of related objects when you update an object, any existing related objects not included in the list will be deleted. For these, you provide yourId
, but you don’t get a machineLabsId
– you just update them by reuploading the parent object.
Subscriptions
Once you’ve uploaded contacts, you can use the updateSubscriptions
mutation to subscribe them to mailing lists, or unsubscribe them. Use the customMailingListSubscriptions
argument to subscribe contacts to any custom mailing lists you’ve uploaded using uploadMailingLists
, or newsletterListSubscription
and customersListSubscription
to manage subscriptions to our two built-in lists.
Note that your subscription changes will only take effect if no errors are returned.
Changes will also only be applied if the lastUpdated
value you provide is greater than the last time the relevant subscription was updated in Machine Labs. For example, if you saw a user subscribe to a list in your system at 1pm and push that data at 1:05pm, but they unsubscribed from that same list in Machine Labs at 1:04pm, we’ll treat the data in our system as most up-to-date, and will not make any changes. This will still be treated as a successful update – it won’t return any errors – but no data will be changed at our side, as we’re already up-to-date.
Queries
The API is mostly focused around uploads – not many queries are available. The two main queries are contact
(to fetch contact data) and subscriptionUpdates
(described below).
To look up a collection of contacts with a given set of email addresses or youId
values, you can use the query below. This can be helpful if, for example, an upload query fails because an email address you’re trying to use on a new contact already exists in the system, and you want to check this existing row. Note the use of the edges
object, following the graphql-relay pattern.
query q($emails: [String], $yourIds: [String]) { contacts(emails:$emails, yourIds: $yourIds) { edges { node { yourId machineLabsId email firstName lastName } } } }
Keeping up with subscription changes
If you’re maintaining a contact’s subscription status in your system, you’ll need to keep up to date with any changes to their subscription status in our system.
You can fetch a list of subscription changes in a time period using subscriptionUpdates
. Upload your contacts, store the date/time the upload completed, then regularly fetch the list of updates since you last checked.
query subscriptionUpdates($changedSince: DateTime!) { subscriptionUpdates(changedSince: $changedSince) { edges { node { contactId mailingListId subscribed lastUpdated isNewsletterList isCustomersList } } } }
Special mailing lists
Machine Labs has some special built-in mailing lists that will be created automatically. Two have special fields for them on subscriptionUpdates
results – isNewsletterList
and isCustomersList
, to indicate that the subscription is for a given special list, rather than a normal one. Similarly, uploadContacts
has special fields on contacts for these subscriptions – newsletterListSubscription
and customersListSubscription
.
The third built-in mailing list – checkout abandonment – is not accessible via the API, and is managed completely by Machine Labs based on the checkouts you update via uploadCheckouts. Make sure to sync your checkout data with us regularly to keep the checkout abandonment list up to date.