Run an automation for a contact
const url = 'https://api.getsitecontrol.com/v1/sites/1/automations/1/runs';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"contact":{"email":"jane@example.com","first_name":"Jane"},"data":{"order_id":"A-981","total":129.9}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.getsitecontrol.com/v1/sites/1/automations/1/runs \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "contact": { "email": "jane@example.com", "first_name": "Jane" }, "data": { "order_id": "A-981", "total": 129.9 } }'Queues a run of the automation for one contact and answers 202 at once. Runs
an automation that is on and has the manual or the webhook
trigger (find them with list_automations by trigger_type, is_active
set to true). Needs the emails.full permission.
The body names the contact by contact_id or gives it as contact, exactly
one of the two. contact is created or updated by e-mail as
upsert_contact does, then run; a status the contact cannot take refuses
the run and writes nothing. It needs contacts.edit on top of
emails.full and spends the contact creation limit, even when the
automation refuses the run. A
limit hit here is not kept under the Idempotency-Key: the same key runs
again once the window passes. The contact and the run are saved together:
on 202 both are; on any error, neither is.
The two triggers run differently:
manualis a sequence of steps that other automations start too. A contact is in it once at a time: while its run is queued or going on, a new run is refused. Once the run finishes, the contact may be run again. Other manual starts (the dashboard, contact imports, the “start automation” step) honour the same check; starts by other trigger types and bulk event packs are not seen by it. A run that failed may be repeated at once through this operation only: the other manual starts skip a contact whose run in this automation failed.datais not read.webhooktakes an event with its values: every call is a new run, also for a contact already in the automation.datareaches the steps as{{$webhook.<key>}}, the values its e-mails and conditions use; the contact is{{$contact.<field>}}. The automation’swebhook_urlfromget_automationstarts the same automation without credentials, for a service that can only send a request: it takes a flat body, finds the contact in it and answers before the automation is checked. Its whole body is$webhook, while here$webhookholds onlydata: a value the automation reads from$webhook, the e-mail included, goes intodata.
The response carries no run id: the run waits to start; follow it with
list_automation_runs by contact_id and order=newest. Send an Idempotency-Key to
retry safely: a retry with the same key gets the stored 202, not a 409.
An unsubscribed contact is run as well, but the steps send it no e-mails.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Automation id from list_automations
Automation id from list_automations
Header Parameters
Section titled “Header Parameters”Makes a retry of a POST safe: a repeat with the same key, body and GSC-Version returns the stored response with Idempotency-Replayed: true instead of running again. The key protects against repeated execution while the key store works. Saving the change and storing the response under the key are not atomic: if the process or the key store fails between them, the change is kept, the key is released after 15 minutes and a retry runs the request again. After a timeout or a 5xx, read the resource to check the result before retrying. 5xx and 429 responses and responses over 256 KB are not stored, so a repeat runs the request again. A key is kept for 24 hours. The same key with another body or version is 422; a repeat while the first request runs is 409.
Makes a retry of a POST safe: a repeat with the same key, body and GSC-Version returns the stored response with Idempotency-Replayed: true instead of running again. The key protects against repeated execution while the key store works. Saving the change and storing the response under the key are not atomic: if the process or the key store fails between them, the change is kept, the key is released after 15 minutes and a retry runs the request again. After a timeout or a 5xx, read the resource to check the result before retrying. 5xx and 429 responses and responses over 256 KB are not stored, so a repeat runs the request again. A key is kept for 24 hours. The same key with another body or version is 422; a repeat while the first request runs is 409.
Request Bodyrequired
Section titled “Request Bodyrequired”Exactly one of contact_id and contact.
object
Id of an existing contact of the site, from list_contacts; leave it out when contact is given
A contact by e-mail, created or updated as upsert_contact does, then run; email is required. A status the contact cannot take refuses the run. Leave it out when contact_id is given. Needs the contacts.edit permission
object
Finds the contact, without case; kept as stored when found, stored in lower case when created
subscribed or unsubscribed; bounced is set only by e-mail delivery. Left out: unchanged, a new contact is subscribed; may not be null
Null clears it
Null clears it
ISO 3166-1 alpha-2 code or an English country name; stored as the code; null clears it
In the international format, or national with country in the same request; stored normalized; null clears it
IANA time zone name such as Europe/Berlin; null clears it
ISO 639-1 code such as de; stored in lower case; null clears it
Values by field id from list_contact_fields: a string for text, a whole number for integer, a number, an ISO 8601 string for a datetime (UTC without an offset), YYYY-MM-DD for a date, true or false for a boolean. Fields of the other type are read-only. Merged into the stored values: null removes a value, keys not given stay as they are
object
Tag names to add, compared without case; a tag the site does not have is created. Tags the contact has stay
Tag names to remove, compared without case; a name with no tag, or a tag the contact does not have, is no change. Never creates a tag
Values for the steps of an automation with the webhook trigger: each key is {{$webhook.<key>}} in its e-mails and conditions. $webhook holds only these values; the contact is {{$contact.<field>}}. A manual automation does not read them.
{ "contact": { "email": "jane@example.com", "first_name": "Jane" }, "data": { "order_id": "A-981", "total": 129.9 }}Responses
Section titled “Responses”object
The contact run; for contact, the one created or found
{ "automation_id": 1, "contact_id": 1}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
True when the response is a stored one, replayed
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
Authentication scheme: Bearer
forbidden: no emails.full permission, or no contacts.edit for contact; account_suspended: the site is suspended; feature_unavailable: the plan has no automations
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
site_not_found, automation_not_found; contact_not_found: no contact of the site with contact_id
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
automation_inactive: the automation is off, turn it on with enable_automation; automation_not_startable: its trigger is neither manual nor webhook; run_in_progress: the contact is in this manual automation, metadata.state is queued (waiting to start) or ongoing (going on, waiting in a delay or on hold); contact_email_taken: another request took the e-mail of contact at the same moment; idempotency_in_progress: a request with the same Idempotency-Key is still running
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
validation_failed; for contact, a field, tag or status transition refused, or the contact unreadable; idempotency_key_reused
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds
Seconds until the bucket refills
temporarily_unavailable: for manual, a bulk start of this automation was being saved and the call waited for it longer than the 25-second request timeout, or rate limits or idempotency keys cannot be enforced; retry later
The documented shape of every error body on the versioned surface.
object
object
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "reason": "example", "next": "example", "request_id": "example", "errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ], "metadata": {}}Headers
Section titled “Headers”API version the response was produced for
Request id, echoed from the request when valid
Limit of the tightest bucket
Requests left in its window
End of its window, epoch seconds