A profile needs a schema for validation and allowing UI (and the rest of the platform) to know which fields are available, their type etc.
Let’s assume we would only like to store the following information on profiles: email, name and interests and transactions made.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "profiles",
"description": "Profile Schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "ID"
},
"firstname": {
"type": "string",
"description": "Firstname"
},
"lastname": {
"type": "string",
"description": "Lastname"
},
"email": {
"type": "string",
"description": "Email"
},
"interests": {
"type": "object",
"properties": {
"biking": {
"type": "string",
"description": "Biking"
},
"tennis": {
"type": "string",
"description": "Tennis"
}
}
},
"transactions": {
"type": "array",
"description": "transactions",
"items": {
"type": "object",
"title": "Transactions",
"properties": {
"id": {
"type": "string",
"description": "id"
},
"TransactionId": {
"type": "string",
"description": "TransactionId"
},
"TransactionDate": {
"type": "string",
"format": "date-time",
"description": "TransactionDate"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
},
"TransactionItems": {
"type": "array",
"description": "TransactionItems",
"items": {
"type": "object",
"title": "TransactionItems",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"price": {
"type": "number"
},
"currency": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
}
All API requests require an authorization token, which can be retrieved using the login service.
A token expires after 6 hours
POST /login HTTP/1.1
Host: api.flowstack.com Content-Type: application/json
{"username":"rune@flowstack.com","password":"secretpassword"}
{"token": "<TOKEN>"}
GET /v1/profiles
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"pagesCount": 1,
"items": [ {profileobj},
{profileobj},.. ],
"total": 12, "page": 1, "limit": 15
}
GET /v1/profiles/4c5af400-b61f-11e7-a352-cd08a6c5d7e0
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"company": null,
"createdAt": "2018-01-15T08:36:53+00:00", "customerSince": null,
"email": "rune@flowstack.com", "firstname": "Rune",
"id": "3cf40120-f9cf-11e7-9f0f-976af719886b", "lastname": "Viem",
"updatedAt": "2018-01-15T08:50:35+00:00", "orders": [
{
"createdAt": "2018-01-15T08:44:14+00:00", "id": "43b8ae60-f9d0-11e7-b7a8-6d47e15f2f2c", "orderdate": "2018-01-14 09:41:00+01:00", "updatedAt": "2018-01-15T08:50:35+00:00", "products": []
} ]
}
POST is used for creating new entity or doing partial update of existing entity
POST /v1/profiles HTTP/1.1
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"firstname": "John",
"lastname": "Doe",
"email": "johndoe@flowstack.com"
}
{
"id": "0212c940-ff58-11e7-b4c4-1b53acbcad21"
}
POST /v1/profiles/0212c940-ff58-11e7-b4c4-1b53acbcad21 HTTP/1.1
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"firstname": "Johnny"
}
{
"company": null,
"createdAt": "2018-01-22T09:38:31+00:00",
"email": "johndoe@flowstack.com",
"firstname": "Johnny",
"id": "0212c940-ff58-11e7-b4c4-1b53acbcad21",
"lastname": "Doe",
"updatedAt": "2018-01-22T09:38:31+00:00",
"transactions": []
}
PUT /v1/profiles/0212c940-ff58-11e7-b4c4-1b53acbcad21 HTTP/1.1
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"firstname": "Johnny"
}
{
"company": null,
"createdAt": "2018-01-22T09:42:54+00:00",
"customerSince": null,
"email": null,
"firstname": "Johnny",
"id": "0212c940-ff58-11e7-b4c4-1b53acbcad21",
"lastname": null,
"updatedAt": "2018-01-22T09:42:54+00:00",
"transactions": []
}
As you see in the result, all attributes are reset unless specified in the body of the PUT.
DELETE /v1/profiles/0212c940-ff58-11e7-b4c4-1b53acbcad21 HTTP/1.1
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
POST /v1/profiles/6142a7e0-ff59-11e7-b4c4-1b53acbcad21/orders HTTP/1.1
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"orderdate": "2018-01-22T10:48:20+01:00"
}
{
"createdAt": "2018-01-22T09:51:05+00:00",
"id": "c39a48d0-ff59-11e7-9eae-d330f583334d",
"orderdate": "2018-01-22T10:48:20+01:00",
"updatedAt": "2018-01-22T09:51:05+00:00",
"products": []
}
Updating or deleting specific order is done using POST or DELETE on full path to specific subentity E.g.
POST /v1/profiles/6142a7e0-ff59-11e7-b4c4-1b53acbcad21/orders/c39 a48d0-ff59-11e7-9eae-d330f583334d HTTP/1.1
POST /v1/profiles:permissions/6142a7e0-ff59-11e7-b4c4-1b53acbcad21 HTTP/1.1
Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{"792":true}
{
"792":true
}
Visitor id: 747089024 (retrieved via fs get_visitor_id)
Profile id: dca17f534d95c0006801f535209f1c1317111fa5
POST /v1/visitors/747089024/e5ce3871446f1146f3ec9ee4fcfb2b02 HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
Returns 200 if successful (no body)
This service should never be called from browser. Web page should never allow script kiddies to change profile/visitor relations.
GET /v1/contents HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"items": [
{
"_key": "f698453c-d948-470c-9399-43b9baef429e",
"id": "f698453c-d948-470c-9399-43b9baef429e",
"name": "",
"type": "",
"content": "{{#eq profile.profile.ecomcategory \"sports\"}}{{/eq}}{{#eq profile.profile.ecomcategory \"fashion\"}} {{/eq}}",
"fallback": " ",
"createdAt": "2019-03-18T10:24:19Z",
"updatedAt": "2019-03-18T10:24:19Z"
}
],
"limit": 25,
"page": 1,
"pagesCount": 1,
"total": 1
}
GET /v1/contents/<SNIPPET ID> HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
Snippets can be rendered frontend side with the jstool.
If a profile is assigned to the visitor, the snippets content property is rendered with the profiles data.
If no profile is assigned, the fallback will be output.
POST /v1/contents HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"content": "<YOUR CONTENT WHICH CAN CONTAIN HANDLEBARS CODE>",
"fallback": "<YOUR FALLBACK CONTENT>"
}
POST /v1/contents/<SNIPPET ID> HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"content": "<YOUR CONTENT WHICH CAN CONTAIN HANDLEBARS CODE>",
"fallback": "<YOUR FALLBACK CONTENT>"
}
DELETE /v1/contents/<SNIPPET ID>
HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
POST /v1/sendouts
HTTP/1.1 Host: api.flowstack.com
Content-Type: application/json
Authentication: <TOKEN>
{
"name":"", // Sendout name - defaults to name of Email message
"emailId":"", // Id of email message
"segmentId":"", // Id of segment, which email will be sent to (recipients)
"onceOnly":, // Remove recipients from sendout who already received email
"removeDuplicates": // Remove duplicate recipients,
"duplicatePath":"", // Property used as duplicate identifier (typically "email")
"duplicateUse":"", // If duplicates use "newest" or "oldest" profile (based on createdAt)
"sendType":"", // Use "now" or "later" depending on whether you want to sendout immediately or at a later time
"sendAt":"", // Time to sendout (e.g. "2019-05-16T08:00:00.435Z")
"subject":"", // Email subject
"fromName":"", // Name of sender
"fromEmail":"", // Sender email
"emailPath":"", // Property containing email address (typically "email")
"emailType":"", // Type of message (marketing or transactional)
"permissionIds":[] // If marketing message, recipients need at least one of permissions provided. Marketing message will not be sent, if no permission(s) provided
}