Getting Started with APIs
Page Contents
- Base URL
- HTTP Verbs Convention
- GET
- POST
- PUT
- DELETE
- Authentication
- OAuth2 Authentication Scheme
- Basic Authentication Scheme
- Authorization
- Rate Limiting
- Content negotiation
- Special Characters in Paths
- Dates and Time
- Pagination
- Parameters
- Response Data
- Collection Filtering
- Selectors
- Operators
- Arguments
- Wildcards
- Dates and Time
- Filtering Examples
- Contextual Data
- Context Parameter Schemas
- Errors
- Basic rules and best practices
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==" ...
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 UAR (Unique 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 a404 (Not Found)
. Note though, that a page size longer than the document size is allowed. This meanspage start + page size > document
size works ifpage 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 HTTPPUT
operationsDelete
– Tries to delete all the records like atomic HTTPDELETE
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 toapplication/json; charset=utf-8.
Agillic only accepts JSON request payloads at time of writing. - If your client uses
Accept
headers; use the MIME typeapplication/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, while5xx
indicate that there is something wrong on our end. If you are receiving4xx
error codes, make sure your requests follow the documentation available here at Agillic Developers.