Create a custom activity event (create)
The create Ortto endpoint of the activities entity is used to create one or more custom activity events in Ortto’s customer data platform (CDP). Creating and managing activity definitions is handled using the activity entity.
All field types are supported when creating a custom activity definition, and follow the same rules and limits as when creating a field in the Ortto app.
This page provides descriptions of this endpoint’s:
- the response payload.
HTTP method and request resources
POST https://api.ap3api.com/v1/activities/createNOTE: Ortto customers who have their instance region set to Australia or Europe will need to use specific service endpoints relative to the region:
Australia: https://api.au.ap3api.com/ Europe: https://api.eu.ap3api.com/For example: https://api.eu.ap3api.com/v1/<entity/endpoint>
All other Ortto users will use the default service endpoint (https://api.ap3api.com/).
Path and query parameters
This endpoint takes no additional path and/or query parameters.
Headers
This endpoint requires a custom API key and content type (
application/jsonfor the request body) in the header of the request:
X-Api-Key: CUSTOM-PRIVATE-API-KEYContent-Type: application/jsonRequest body
The request body consists of a JSON object with the valid elements listed in the table below.
The following JSON objects are examples of requests to create custom activities in your Ortto account’s CDP.
Example create custom activity event request body
json
{ "activities": [ { "activity_id": "act:cm:flight-booked", "attributes": { "int::v": 15300, "str:cm:destination": "London", "str:cm:carrier": "Easy Jet" }, "fields": { "str::first": "Billie", "str::last": "Holiday", "str::email": "billie.holiday@email.com" }, "location": { "source_ip": "172.217.4.1", "custom": null, "address": null } } ], "merge_by": [ "str::email" ] }You can also merge person records using a person’s ID. This approach restricts the updates you can make to the contact at the same time as raising the activity, but it results in much faster processing since the direct contact is known and doesn't need to be looked up using a filter.
NOTE: If merging by a person’s ID, simply provide a
person_idvalue, when doing this, you do not need to include themerge_byfield. Also, any data passed in via thefieldsobject will be ignored if merging viaperson_id.Example create custom activity event request body and merge by a person’s ID
json
{ "activities": [ { "activity_id": "act:cm:flight-booked", "person_id": "00671822e88c13e21abf2302", "attributes": { "int::v": 15300, "str:cm:destination": "London", "str:cm:carrier": "Easy Jet" }, "location": { "source_ip": "172.217.4.1", "custom": null, "address": null } } ] }If your activity contains an attribute that is a JSON object, you can structure the attribute’s JSON object with or without values assigned to a variable – see the example below.
Either approach will enable you to loop through the values using Liquid syntax in an email campaign, the only difference will be in how you reference the object. Learn more in Access JSON objects with Liquid.
Example create custom activity event request body with JSON object attributes
json
{ "activities":[ { "activity_id":"act:cm:activity-with-json-object", "attributes":{ "obj:cm:product-array":[ { "item_id":"12345", "item_name":"Timber stand-up desk", "price": 1000, "currency": "USD", "item_brand": "Standy", "supplier": "Standy", "item_variant": "walnut/black", "item_category": "Stand up desks" } ], "obj:cm:products":{ "products": [ { "item_id": "12346", "item_name": "Laminate stand up desk", "price": 800, "currency": "USD", "item_brand": "Standy", "supplier": "Standy", "item_variant": "walnut/white", "item_category": "Stand up desks" } ] } }, "fields":{ "str::email":"contact@email.com" } } ], "merge_by":["str::email"] }Depending on the merge strategy configured for your custom API key, sending activity data for a person who does not match an existing contact in your CDP may create that person as a new contact. By default, all people added via the API are considered to be "opted in" for email subscription permission.
To send an create an activity event that contains an email subscription permission, include in
fields:
bol::p— a field representing permission that takes a value oftrueorfalse
str::s-ctx— a field used to create a message identifying how the person was subscribed/unsubscribed.In an activity event request, that would look like:
Example create custom activity event with subscription permission request body
json
{ "activities": [ { "activity_id":"act:cm:logged-in", "attributes": { "str:cm:payment-plan": "Free plan", "bol:cm:account-owner": true, "str:cm:web-browser": "Netscape Navigator" }, "fields": { "str::first": "Chris", "str::last": "Smith", "str::email": "chris.smith@example.com", "bol::p": false, "str::u-ctx": "Unsubscribed via internal API" } } ] }Learn more about email permission and activities.
If necessary, you can override your API key’s merge strategy by including
merge_strategyand the required value (1— append only,2— overwrite existing, or3— ignore) in the request. Learn more about setting a merge strategy.About asynchronous activity ingestion
For asynchronous activity ingestion, add the
"async": trueflag to the request. Learn more about asynchronous activity ingestion.When sending activity events for activities that are older than 90 days (where data retention is enabled), the activity ingestion will be buffered, even if
"async": false.Custom activity request limits
It is possible to send up to 100 activities in the one payload to Ortto. The limits are as follows:
100 activities max 2 MB total payload sizeIn addition to the above, the number of activities per contact per day is limited. The limit is 50 activity events per activity per contact per 24 hours. See an example illustrating this limit under Custom activity request limits in the Custom activities guide.
Valid request body elements
The following table lists all valid request body elements (arrays, objects, or fields), which are available to this endpoint.
Element
Type
Description
activities
arrayof objectsThe
activitiesarray consists of an array of objects where each object contains data associated with an activity event being created in your Ortto account’s CDP. Each of these objects can contain:•
activity_idand activityattributesobjects•
fieldsandlocationobjects.
activity_id
stringThe ID for the custom activity.
attributesObject containing activity attributes
The field IDs for the custom activity attributes. (Note this is independent of person field IDs.)
The conversion value is set at
int::v. The value is currency and must be multiplied by 1000. Using the example above,"int::v": 15300, sets the conversion value attributed to the activity at $15.30
fieldsObject containing person fields.
The object containing the fields for a person being created or updated in your Ortto account’s CDP. This person is either created or updated in Ortto’s CDP based on these criteria:
If thisfieldsobject contains a person field ID whose value matches themerge_byID value submitted in this request, and this person field’s value does not match that of an existing person in Ortto’s CDP, then Ortto creates this person as a new record. Otherwise, if the person field ID value does already match that of an existing person in Ortto’s CDP, then Ortto updates the fields of that person’s record in the Ortto CDP, according to themerge_strategyset for your Ortto custom API data source.
locationObject containing location field data
The
locationobject either accepts a single IP address (as asource_ipfield member) or a full address (in either acustomoraddressobject).The
locationobject provides more flexible options for specifying a person’s location and address details rather than having to specify this information viageo-type person fields in afieldsobject.merge_by
arrayof one or twostringvaluesThe
merge_byelement’s array allows up to two field ID values that specify the person fields used to determine whether the people’s records are either created or updated in your Ortto account’s CDP.When the value of the person field ID (determined by the relevant
merge_byvalue), submitted in this request matches that of an existing person in Ortto’s CDP, then this person’s record is updated in the CDP and where appropriate, existing field values are merged according to themerge_strategyset for your Ortto custom API data source. Otherwise, Ortto creates a new person’s record in the CDP.These values override the default person fields associated with the custom API key with the
merge_byfields submitted in this request. These default field values are defined by the Merge strategy associations configured for this custom API key. If amerge_byelement is not specified in the request, then these default person field values are utilized instead. The first of these values determines the mainmerge_byperson field utilized by Ortto in the request, whereas the second (optional) value determines the fallbackmerge_byperson field (which behaves as a backup should the first field - e.g. a custom field - not be available within the person’s record of Ortto’s CDP).About empty values
When you use a filter to search for people, the Has any value filter option will find matches for activity attribute and field values that have a value of
0or""(empty string). However, Has any value won’t find attribute or field values that arenull.You can set values according to your needs by updating a person’s data using this API endpoint (
v1/activities/create). To:
Include an empty value in a search: set an existingnullto0or"". Exclude an empty value from search: set an existing""or0value tonull.For example, updating a person’s activity attribute and field values to exclude them from search can look like this:
"activities": [ { "activity_id": "act:cm:flight-booked", "attributes": { "str:cm:destination": null }, "fields": { "str::first": "Kate", "str::last": "Traveller", "str::email": "kt@holiday.com", "str:cm:member-id": null },Response payload
The response payload consists of a JSON object with the elements listed in the table below.
The following JSON object is an example of people’s data that Ortto retrieves from your Ortto account’s CDP after a request to this endpoint.
Example create custom activity event response payload from Ortto’s CDP
json
{ "activities": [ { "person_id": "0063f2c474449cd58a4c5600", "status": "ingested", "person_status": "created", "activity_id": "0063f2c474bc15d72affcdcc" } ] }Response payload elements
The following table lists all elements (arrays, objects, or fields) in the response from a request to this endpoint.
Element
Type
Description
activities
arrayof objectsThe
activitiesarray consists of the activity event data.The list of responses correlates to the array of activity events that were sent in the request. So if you sent 2 activities in your request, index 2 in the response is your result for index 2 in the request. See an example of sending multiple activities and the responses under Custom activity request limits.
person_id
stringThe unique identifier for the CDP contact.
status
stringThe
statusvalueingestedindicates that the activity event has been synchronously ingested.If you used the
"async": trueflag in the request, then thestatusvalue will bequeued.
person_status
stringIdentifies the status of the person associated with the activity. Learn more about
person_statusvalues under Create activity response.If you used the
"async": trueflag in the request, then theperson_statusvalue will bequeued.
activity_id
stringThe unique identifier for the activity event.
Backdating activities
If you would like to backdate activity data, you can use the
createdfield in your request to specify the date on which the activity occurred. Ortto allows you to send in backdated events up to 90 days in the past, or if you have data retention enabled on your activity, you may provide backdated events up to your selected data retention period.In addition, to make sure you do not backfill the same piece of data more than once, you can include a
keyattribute, which gets combined with thecreateddate to create a unique identifier for each activity. If you provide the same pair forkeyandcreatedmultiple times (such as if you need to run your backfill scripts multiple times), it will merge those requests so you do not get duplicate activities created.json
curl --location\ --request POST 'https://api.ap3api.com/v1/activities/create'\ --header 'X-Api-Key: PUT-YOUR-REAL-KEY-HERE'\ --header 'Content-Type: application/json'\ --data-raw '{ "activities": [ { "activity_id":"act:cm:logged-in", "created": "2020-02-17T01:30:17.601Z", "key": "125432", "fields": { "str::first": "Chris", "str::last": "Smith", "str::email": "chris.smith@example.com" }, "attributes": { "str:cm:payment-plan": "Free plan", "bol:cm:account-owner": true, "str:cm:web-browser": "Netscape Navigator" }, "location": { "source_ip": "59.167.135.194" } } ] }'As this documentation will age, if you copy the above example verbatim you might get a response like below:
json
{ "request_id": "19ccd5c1-112d-4dfa-bf80-0a3312896742", "code": 400, "error":" Created date is more than 90 days ago" }If you provide a
createddate within the last 90 days (or within your activity’s selected data retention period), you will receive a successful response:json
{ "activities": [ { "person_id":"00602c446af92b7aa1f77a00", "status":"ingested", "person_status":"created", "activity_id":"00602c71a9b346c32c9b7473" } ] }If you provide a
createddate outside of the activity’s selected data retention period, you will receive an error response:json
{ "request_id": "19ccd5c1-112d-4dfa-bf80-0a3312896742", "code": 400, "error":" Created date is outside of activity cold storage" }NOTE: Activities that are more than 90 days old and within the activity’s selected data retention period will be added to a queue for processing which may take up to an hour.
Learn more about configuring data retention.