Skip to content

Running integrations from the API

An integration you have built in Settings > Integrations can be run from your own software as well as from a job. The API queues the run, a worker calls the other service, and you read the result back with the id the queue gave you.

You need a key with execute:integrations to start a run and read:integrations to read one back. A key that only starts runs cannot read them.

Terminal window
curl -X POST https://api.workwing.io/v1/integrations/execute \
-H "Authorization: Bearer ww_sk_live_abc123.xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"integrationId": "0199a1b2-c3d4-7000-8000-000000000001",
"inputData": { "postcode": "SW1A 1AA" }
}'

The reply comes back straight away with the id of the queued run:

{
"data": {
"queueId": "0199a1b2-c3d4-7000-8000-0000000000aa",
"status": "T_PENDING",
"message": "Integration queued for execution. Poll GET /v1/integrations/executions/0199a1b2-c3d4-7000-8000-0000000000aa for the result."
}
}

Keep the queueId. It is how you read the result, and it is the only thing that identifies this particular run.

Terminal window
curl https://api.workwing.io/v1/integrations/executions/0199a1b2-c3d4-7000-8000-0000000000aa \
-H "Authorization: Bearer ww_sk_live_abc123.xxxxxxxx"
{
"data": {
"queueId": "0199a1b2-c3d4-7000-8000-0000000000aa",
"status": "T_COMPLETED",
"executionId": "0199a1b2-c3d4-7000-8000-0000000000bb",
"executionStatus": "T_COMPLETED",
"output": { "line": "active", "speed_mbps": 900 },
"completedAt": "2026-09-13T09:14:22.418Z"
}
}

output is the integration’s transformed output: the same values its output parameters produce when a job runs it. The other service’s raw reply is not returned here. It is kept with the run and shown in the execution log on the integration’s own page, where the people who configured the integration can read it.

There are two statuses because there are two things happening. Read the run again, once a second, while either of them is still pending.

status the queued work: T_PENDING, T_RUNNING, T_COMPLETED, T_FAILED
executionStatus the integration itself, which for a run whose result arrives
by callback stays T_PENDING until the other service posts back,
then becomes T_COMPLETED, T_FAILED or T_EXPIRED

For a run whose result arrives by callback, status reads as completed as soon as the request has been sent, so wait on executionStatus instead. output fills in from the callback once executionStatus reads as completed.

A run that failed answers 200 with status set to T_FAILED. The other service’s error text is recorded against the run rather than returned, so read the execution log on the integration’s page to see what it said.

An id that does not exist, and an id belonging to another organisation, both answer 404.

Add ?wait=true and the call holds open until the run finishes, then answers with the run itself instead of just the queue id:

Terminal window
curl -X POST "https://api.workwing.io/v1/integrations/execute?wait=true" \
-H "Authorization: Bearer ww_sk_live_abc123.xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"integrationId": "0199a1b2-c3d4-7000-8000-000000000001", "inputData": {}}'
{
"data": {
"queueId": "0199a1b2-c3d4-7000-8000-0000000000aa",
"status": "T_COMPLETED",
"executionId": "0199a1b2-c3d4-7000-8000-0000000000bb",
"executionStatus": "T_COMPLETED",
"output": { "line": "active", "speed_mbps": 900 },
"completedAt": "2026-09-13T09:14:22.418Z",
"result": {
"executionId": "0199a1b2-c3d4-7000-8000-0000000000bb",
"status": "T_COMPLETED",
"output": { "line": "active", "speed_mbps": 900 },
"cacheHit": false
}
}
}

The fields are the ones GET /v1/integrations/executions/{queueId} returns. result repeats the run’s status and output as earlier versions of this reply carried them, plus cacheHit, which is true when the output came from the integration’s cache rather than a fresh call. For an integration whose result arrives by callback, the wait ends once the request has been sent, so executionStatus still reads as pending: read the run back by its queue id for the outcome.

How long it will hold is the Timeout (minutes) on the integration’s General tab, capped at five minutes.

If the wait runs out you get a 408 carrying the queueId. The run has not been cancelled. It is still going and it will still finish, so read it back with the queue id above. Sending the same execute call again starts a second run, and if the integration books, charges or provisions something, it will do it twice.

If the run itself fails you get a 422 carrying E_AP_7003, with the queueId and executionId in error.details. As on the async path, the other service’s error text is recorded against the run rather than returned; read the execution log on the integration’s page.

Waiting inline suits a run that is quick and whose answer you need before you can do anything else, such as filling in a form the person is looking at. For anything else, take the queue id and read the result back.