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 and your brand ID when you signed up – you’ll need this for all requests.

To get a full list of available queries, mutations, and types, and try out some requests visit https://demoapi.machinelabs.com/v1/ to use our graphiQL instance. You’ll need your API key and brand ID, as you’ll be running these requests against your live account.

The documentation below provides general information on how all of these mutations work, which you can combine with the graphiQL documentation above to get the signature for any specific query or mutation.

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($apiKey: String!, $brandId: ID!, $mailingLists: [MailingListInput]!) {
    uploadMailingLists(apiKey: $apiKey, brandId: $brandId, mailingLists: $mailingLists) {
        result {
            yourId
            machineLabsId
        }
        errors {
            message
        }
    }
}

and could use these variables:

{
    "apiKey": "yourAPIKey",
    "brandId": 1,
    "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.

{
    "apiKey": "yourAPIKey",
    "brandId": 1,
    "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"
        }
      ]
    }
  }
}

with a message that should explain what needs fixed. 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
  }
}

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

All queries need to provide an API key and brand ID to getBrand, as below (this just echoes your brand ID back to you if you’ve given valid credentials):

query brand($apiKey: String!, $brandId: ID!) {
    getBrand(apiKey: $apiKey, brandId: $brandId) {
        brand {
            id
        }
        errors {
            message
        }
    }
}

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 brand($apiKey: String!, $brandId: ID!, $changedSince: DateTime!) {
    getBrand(apiKey: $apiKey, brandId: $brandId) {
        brand {
            id
            subscriptionUpdates(changedSince: $changedSince) {
                edges {
                    node {
                        contactId
                        mailingListId
                        subscribed
                        lastUpdated
                        isNewsletterList
                        isCustomersList
                    }
                }
            }
        }
        errors {
            message
        }
    }
}

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.