Getting Started with APIs

Agillic’s APIs are REST based and designed to be resource-centric. By resource-centric, Agillic suggests that for a specific resource (e.g. Recipient, Flow, Global Data Table), an API dedicated to that resource is implemented in order to expose the business logic relevant for that resource. This is the reason why Agillic exposes APIs such as: Recipient API, Flows API or Global Data API.

The Agillic APIs are designed for developers, engineers, or anyone else who’s familiar with integrating with RESTful APIs. Unsure if you fit this description? Please consult our Support Team before you start your integration.

Base URL

The same Base URL is used for all Agillic REST APIs. [ Base URL: https://api-eu1.agillic.net ] Use Base URL as base path for your requests.

Example

curl https://api-eu1.agillic.net/recipients ...

Examples presented in this section should not be considered as a template for requests, but rather a developer aid for understanding and using REST APIs. Please use API Documentation sections for instructions on how to use the APIs.

HTTP Verbs Convention

Agillic REST APIs are designed to be user-friendly. We strive to adhere to the HTTP specification to ensure the APIs are as predictable and standard as possible. Below you will find our interpretation of the HTTP verbs and a description of how you can expect them to behave in general.

GET

GET will return a single resource or a collection identified by the URI.

POST

POST is used for creating new entries in collections, e.g. a new recipient in the recipients collection. POST will in this case return a 201 Created when successful. POST is also used for all custom methods returning 200 OK, regardless of the purpose of the operation.

PUT

PUT will update the specified resource by replacing it. Example: If you PUT a recipient, the request URI must contain the ID of the recipient – the request will then either create, or update the entity if it exists. PUT will clear the Person Data fields of the target recipient, if the fields are included in the call, but empty or null.

PUT requests to the Agillic APIs will have upsert behavior; i.e. when using a resource ID that does not exist in Agillic, the resource will be created having the specified ID, returning 201 created. If the ID is known by Agillic the resource will be updated as explained above. This is especially useful when Agillic is not data master and synchronization from data master to Agillic is required.

DELETE

DELETE requests will delete the resource identified by the request URI.

The client cannot be guaranteed that the operation has been carried out, if internal constraints prevent the deletion. Examples of internal constraints are a resource being in use, or being dependent by another resource. In these cases, make sure that the resource is intended to be deleted and eliminate the constrains.

Example

Authentication

Access to the APIs are restricted and needs to be authenticated and authorized. The authentication implementation is OAuth2 – supporting both a two- and three-legged authorization flow. Before starting the authorization flow, API credentials has to be created in the Agillic instance.

How to create API credentials

  • Log into Agillic instance
  • Open the ‘Administration’ module
  • Open the ‘Integrations’ section
  • Open the ‘API’ subsection
  • Navigate to the environment – staging or production – for which you want the credentials
  • Enter a description of what the API credentials will be used for
  • Choose an appropriate scope for your credentials
  • Click on ‘Create new credentials’ button and complete registration

The credentials (Developer Key and Secret) are now ready to be used for authorizing REST API calls.

OAuth2 Authentication Scheme

OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices. This specification and its extensions are being developed within the IETF OAuth Working Group.

Request access token

Use the OAuth2 endpoint with the Developer Key (client_id) and Secret (client_secret) as data to request the OAuth2 access token:

curl -X POST https://api-eu1.agillic.net/oauth2/token \
--data "grant_type=client_credentials" \
--data "client_id=cwIESVw6o1nK" \
--data "client_secret=X3yGvtaeCYz4i5WL"

The response to this POST will be a JSON string containing the access token that can then be used to access the API.

Time To Live (TTL) is 2 hours

Use the access token in a header to authorize API calls, until the TTL expires.

Basic Authentication Scheme

Basic auth is less secure than Oauth2 and is not recommended

The “Basic” HTTP authentication scheme is defined in RFC 7617, which transmits credentials as developer key / developer secret pairs, encoded using base64. So in order to use the APIs you must provide an Authorization request header constructed as a string on the form: Basic " + Base64.encoded(developer key + ":" + developer secret). The following example show an Authorization header generated from a set of credentials where the developer key (client id) is cwIESVw6o1nK and the developer secret (client secret) is X3yGvtaeCYz4i5WL.

Example

curl -X GET https://api-eu1.agillic.net/recipients \
"Authorization: Basic Z3JlZW4uYmx1ZTpjYW5keQ==" ...

Authorization

Authenticated requests are restricted to a subset of API operations which is known as a scope (not to be confused with an OAuth scope). A scope is assigned to a developer key in the Api section of the Settings. Currently, Agillic has two main API Scopes for Credentials : App Api and Public Api.

  • The App Api Scope is intended for credentials that will be embedded in devices. It is restricted to APIs documented in the Register API section
  • The Public Api Scope is intended for credentials that will be managed securely by the customer. All public API operations are accessible including the Recipients Api.

Rate Limiting

The Agillic Rest API is rate limited. This means we impose certain limits on the API, per production instance, per day. We reserve the right to adjust the rate limit for the given endpoints in order to provide a high quality of service for all customers.

The rate limit enforces the following restrictions on production instances

  • Daily Cap on API calls: 5x times as many API calls as Active Recipients.
  • Concurrent Call Limit: maximum of 20 concurrent API calls
  • Max Payload Size: capped at 20MBs

Example of “Daily Cap”, based on Active Recipients

Active Recipients 200.000 500.000 1.000.000 5.000.000
API calls per day 1.000.000 2.500.000 5.000.000 25.000.000

The amount of Active Recipient is defined in your organization’s Agillic License. Should you need to transfer more data than our API rate limit allows, you should use our bulk methods to import and export recipient data, as described in Data In/Out.

Rate limit for staging instances

We have a flat rate limit on the staging environment of 5000 API calls a day. Remember that all integrations should be developed with test data values (and minimal volume) towards staging, before adjusting the setup to production.

Content negotiation

Requests sent towards Agillic REST APIs must include a MIME type inside HTTP request headers for content negotiation. To communicate an intent of obtaining a specific file type as a result of operation, add Accept header. When providing payload necessary for operation’s success in the request body, provide the MIME type in Content-Type header.

Example

curl -X GET https://api-eu1.agillic.net/recipients \
-H "Authorization: Bearer B4ncIQ0TVBU9Hchp3EI2ZuPD4XWafoqf" \
-H "Accept: application/json; charset=utf-8"

curl -X POST https://api-eu1.agillic.net/globaldata/tables/STORES/record \
-H "Authorization: Bearer B4ncIQ0TVBU9Hchp3EI2ZuPD4XWafoqf" \
-H "Content-Type: application/json; charset=utf-8"
{
"ID" : "New York",
"EMAIL" : "newyork@agilliccandy.com"
}

Currently, Agillic REST APIs only support application/json; charset=utf-8 for all types of requests.

Special Characters in Paths

Most of special characters in paths must be URL encoded twice; i.e. re-encoding the encoded character. When using forward slash /, the first encoding results in %2F and the second encoding results in %252F which can then be used in the request path.

Take a look at this handy cheat-sheet for some commonly used special characters (note that some of them do not need double encoding):

Symbol Sign Encoded Sign
at @ %2540
dot . .
dash
underscore _ _
plus + %252B
exclamation mark ! %2521
hash # %2523
ampersand & %2526
apostrophy %2527
asterisk * *
equals = %253D
question mark ? %253F
back slash \ %255C

Dates and Time

Agillic’s APIs uses the date-time formats specified on each instance, in the Agillic’s Integration: API Settings. The default format is dd.MM.yyyy for dates, and dd.MM.yyyy HH:mm:ss for timestamps.

The filtering API uses the format defined by RFC3339.

Pagination

Pagination will be introduced gradually in the Agillic APIs, starting with the Recipients API.

Pagination is the concept of dividing a document into smaller pages. Clients of a paged API can scroll through these pages in manageable chunks. Delivering pages instead of full documents enables us to provide a faster, better and more stable service. Each page has three components: the content, hypermedia links and metadata (see section “Response Data” below for more information).
The first request to a paged API, will create a document and return the first page of this document. To make additional requests to the same document you have to provide the document id on every call (also returned on the first call).

The time to live (ttl) of a document is restricted to 5 minutes. Each new call to the same document will reset its ttl to 5 minutes until a total of 30 minutes is reached.

Pagination is triggered by adding query parameter objectResponse=true. This will change the response format and also return in pages/chunks.

Parameters

An endpoint implementing the Pagination API has the following parameters:

Name Parameters Default, Min, Max Explanation
Object Response objectResponse true | false This change the response to a paginated format and returns a document id that should be used in subsequent calls.
Filter filter No filter, N/A, N/A This is the filter used to select the resources of the document. Once the document is created it can not be modified anymore. This means filtering only works on the first API call.
Page Start pageStart 1, 1, ∞ This sets the first item of the requested page of the total items in the document.
Page Size pageSize 1000, 1, 1000 This is the number of items on each page.
Document Id documentId N/A This is the document id. It is automatically created by the server and returned to the client after the first request. To access further information in the same document, you need to provide this id.

To make a modified call to a paginated endpoint, just concatenate the different parameters. The first parameter must be preceded by a ?, all others by a &. Like so:

?documentId=jdsSo2iFh2&pageSize=100&pageStart=101

The first call will create a new document with an unique documentId. On this call you may provide a filter. To learn more about filtering see section Collection Filtering.

Response Data

The returned data is a JSON formatted object containing two arrays and one object. The arrays are links and content and the object is page. For a correct call you will get a 200 (OK) and the following response structure:

The content is the requested items from the document.
The hypermedia links are links to request additional items from the same document. They include links to the pages first, prev (if applicable), self, next (if applicable) and last.
The metadata includes information on the size of the document and the current page.

Special cases

  • Filtering until no item is left in the document, will result in a 200 with an empty content array.
  • Using a non-existing document ID will return a 404 (Not Found).
  • Requesting an item which is not in the document, so when page start > document size , will return a 404 (Not Found). Note though, that a page size longer than the document size is allowed. This means page start + page size > document size works if page start <= document size.

Examples

GET /recipients/?filter=LASTNAME=="Blue" and AGE<=20 and AGES<=80&pageSize=100
GET /recipients/?filter=FAVORITE_CANDY_TYPE=in=(Chocolate or Caramel)&pageStart=10000
GET /recipients/?pageStart=3000&pageSize=500
GET /recipients/?pageStart=1000&documentId=x5Lx8eYF23

These examples are not encoded correctly as it would obscure the description. However used in postman or similar software, it would encode correctly.

Collection Filtering

Filtering on collections will be introduced gradually in the Agillic APIs

Collection filtering is done by applying a query parameter filter=<rsql expression> to any endpoint that returns a collection. RSQL (see below) is a query language based on FIQL, that provides a friendly syntax for filtering. The rsql expression is composed of a selector, an operator and an argument.

filter = <selector> <operator> <argument>

Selectors

Selector identifies a field, attribute, element etc. of the resource. Selector must be a non empty Unicode string that doesn’t contain reserved characters: white space, ', ", (, ), ;, ,, =, !, ~, <, >. The Selectors available depend on the given endpoint.

Operators

RSQL expressions are composed of one or more comparisons, related to each other with logical operators:

  • AND and
  • OR or

The AND operator takes precedence. However, a parenthesized expression can be used to change the precedence.

  • Equal to ==
  • Not equal to !=
  • Less than <
  • Less than or equal to <=
  • Greater than >
  • Greater than or equal to >=
  • In =in=
    Note: Unsafe characters needs to be encoded when used in a url. This means that any usage of < (less than) and > (greater than) needs to be encoded as respectively %3C and %3E. In principal = (equals) should also be encoded as %3D, but does work un-encoded with current software stack.

Arguments

The argument is any non-empty value with a restriction on type of the Selector. If the Selector is of type NUMBER the argument must be numeric etc. and if the Selector is of type data it must follow the below date-time format.

Wildcards

Wildcards can be used to represent any character or sequence of characters value inside an argument of type STRING.

  • Matching one character ?
  • Matching a sequence of characters *

Note, that as wildcards are used to represent strings, they only work with the == operator.

Dates and Time

The filtering APIs uses date-time as defined by RFC3339. Below are some examples of valid date-time values.

Example

UTC time zone 2017-04-09T23:20:50Z
Copenhagen CEST 2017-04-09T23:20:50+02:00

If your Date API format directly conflicts with the RFC format, such as dd-MM-yyyy, use your set format to filter instead of RFC. This only applies to filtering on date fields.

Filtering Examples

For clarity the examples are not URL encoded, but how it would be entering in Postman:

GET /recipients/?filter=LASTNAME=="Blue" and AGE>=20 and AGE<=80 
GET /recipients/?filter=FIRSTNAME==White and FAVORITE_CANDY_TYPE=in=(Chocolate or Caramel) 
GET /recipients/?filter=(FIRSTNAME==White or FIRSTNAME==Jane) and AGE>18
GET /recipients/?filter=FIRSTNAME==W?i* or FIRSTNAME==W*
GET /recipients/?filter=CREATED>"01.01.2018 00:00:00"

Inside =in= comparisons you can optionally use , for separation e.g. FAVORITE_CANDY_TYPE=in=(Chocolate,Caramel).

The Query part need to be encoded and is done by by url-encode the query parameter name (filter), append with equal and append with the url encoded value. This means that the first filter above becomes:

This should be done by software. In case of manual testing, Postman does a good job of encoding what is minimum required. You can code to get the exact curl command. Also see RFC 1738: Uniform Resource Locators for details

Contextual Data

Contextual Data is a feature designed to expand the ways data can be used in Agillic outbound communications.

Contextual Data enables marketing teams to:

  • Simplify data flow by triggering communications at the same time as sending the data. Strong use cases exists with transactional emails, although not limited to that usage.
  • Send data to Agillic in a custom data structure, separate from the traditional Agillic Data Structure (Person Data, One To Many Tables, Global Data, Global Data Tables). The Contextual Data’s structure mimics the traditional models, and can be merged into communications as such. The Contextual Data only persists in the flow executions directly triggered by the API call.

Contextual Data is transient in nature – data is available in the scope of the request but will not be stored and cannot be used later – for example in a Condition.

Contextual Data is only available for a subset of API call (see specifications for details).

Contextual Data must be follow a known Context Parameter Schema (see below).

Context Parameter Schemas

Contextual Data sent to Agillic must pass validation against an already defined and published format schema.

This format is called a Context Parameter Schema and is stored as a JSON file in the WebDav Media Browser. You can have multiple Schemas, differentiated by file name.

When making an API call with Contextual Data the Context Parameter Schema must be identified (usually by the name field in a request body – see API documentationfor details).

To set Context Parameter Schemas in Agillic upload them to WebDAV. Follow this path to upload:

* media
** contexts

Some relevant attributes to become familiar with:

Object Description Restrictions
data_type Defines what data format the field should validate with string|number|boolean|date|timestamp
type Defines what Agillic Data Model the structure is person_data|otm|global_data|gdt
required This specific model or field must be present to send communications true|false, default is false

We do not currently allow changes to fields or models in existing Context Parameter Schema files. This is to ensure that live flows can’t be broken by changes to its Schema.

Here’s an example Context Parameter Schema file, named order.json:

Accepted body for the above Schema

Usage

After a Context Parameter Schema is uploaded and validated, a communication can reference the fields from the Content Designer. Read the Knowledge Base guide to merge Contextual Data into your communications.

Custom Methods

REST is currently only concerned with individually-addressable resources and has no way of handling complex operations such as batch processing or other cross-resource operations. Agillic has introduced an URL constructed for custom methods that appends an operation name after a colon. The following example evaluates Promotions for a Recipient and returns a collection of resources that, because of their dynamic nature, are not addressable. All custom methods must be called with HTTP POST method.

Example

POST /recipients/{recipientId}/:evaluatePromotion

Batch processing

The efficiency of using batch operations can vary depending on the complexity and size of the batch. Currently there is a hard upper limit on batch sizes set to 1000 entries.

Batch resource handling is created for fast and efficient execution of the same operation over an entire set of resources. Instead of calling an endpoint multiple times for every resource, you can call an endpoint once, with a set of resources. This way, the overhead of creating and executing multiple HTTP requests is mitigated.

Operations

Batch processing currently includes two operations; Update, and Delete. The operations are not transactional and each entry will be processed disregarding the result of any previous entries.

  • Update – Tries to update all the records like atomic HTTP PUT operations
  • Delete – Tries to delete all the records like atomic HTTP DELETE operations

A short Update example from Recipients API is shown below. More detailed examples on how to use batch processes can be found under the various APIs.

Example

POST /recipients/blue@sweetmail.com/oneToManyTables/PURCHASES/:batchUpdateRecords
[{
    "ID" : "123789",
    "PRODUCT_ID" : "428642",
    "PAID" : "True",
    "STORE" : "Copenhagen",
    "PURCHASE_DATE" : "20.12.2017"
},
{
    "ID" : "123790",
    "PRODUCT_ID" : "427943",
    "PAID" : "False",
    "STORE" : "Copenhagen",
    "PURCHASE_DATE" : "20.12.2017"
}]

Errors

All API errors are presented as HTTP status codes, and in the majority of times without any detailed information in the body of the response. This is to prevent divulging any information that can be used as attack vectors. The exception to this rule is 400 BadRequest and 409 Conflict where a message might be returned to ease development. If the selector in the filter is not present in the database a 422 Unprocessable Entity will be returned.

Example

GET /recipients/FIRSTNAME=green.blue
{
  "message": "Path expression field is not unique"
}

The above message should provide the developer information about the cause of the client error. The Person Data FIRSTNAME is not a unique field in most systems.

Basic rules and best practices

Here are a handful of rules and best practice advice to keep in mind when integrating with the Agillic REST APIs:

  • Remember to authorize yourself by adding the Authorization header with an OAuth2 token every time you use an API endpoint.
  • When using request payloads; send them in UTF-8 and set the Content-Type header to application/json; charset=utf-8. Agillic only accepts JSON request payloads at time of writing.
  • If your client uses Accept headers; use the MIME type application/json. Agillic only provides JSON response payloads at time of writing.
  • Always consider using any of the provided batch operations to optimize your throughput.
  • Our APIs will always indicate the origin of an error by sending a response code with an error message, for example: 4xx codes describe client-side error, while 5xx indicate that there is something wrong on our end. If you are receiving 4xx error codes, make sure your requests follow the documentation available here at Agillic Developers.