Heppu APIv2.heppu.ai/api

Run a job

Kick off one execution, now.

POST/api/v2/jobs/{jobId}/executekey or session

Creates an execution and starts it immediately. For "call this one person right now" pair it with an existing contact id. For inbound or scheduled jobs just post an empty body.

Job must be running or draft and have an assigned worker.

jobContactIduuid
Contact to run for. Must be a contact on this job, or you get a 404. It must be pending with no execution still pending or running on it, or you get a 409. The new execution claims it: the contact moves to in_progress and settles when the execution finishes.
processNowboolean
false leaves the execution at pending for the scheduler.default true
triggerEventIdstring
Your own correlation id. Stored, echoed in webhooks.
attemptNumberint
With a jobContactId, defaults to the contact's current attempt (1 for a contact never tried). Without one, defaults to 1.
curl -X POST https://v2.heppu.ai/api/v2/jobs/JOB_ID/execute \
  -H "x-api-key: hep_..." -H "Content-Type: application/json" -d '{}'
201
{
  "data": {
    "executionId": "3f8e2b91-…",
    "jobId": "…",
    "status": "pending",
    "triggeredBy": "manual",
    "agentId": "…",
    "processingStarted": true
  },
  "meta": { "timestamp": "…", "message": "Job execution created successfully" }
}

status is always pending in this response because the engine starts after we reply. processingStarted: true means we started it, not that it finished. Watch webhooks for the result.

Errors: 400 job not running/draft or no worker assigned, 404 job or contact not found, 403 needs job:execute.

409 when the contact cannot be claimed. Nothing is created and the contact is left as it was:

  • Job contact is held by another execution that has not finished: the contact is in_progress, or its last execution is still pending or running. Retry once that execution ends.
  • Job contact is <status>; only a pending contact can be run: the contact is completed, failed or paused.

Older flavour

POST/api/v1/jobs/{jobId}/triggerkey only

Same idea, but you inline the contact and we don't start the engine. The contact sits at pending until the scheduler picks it up (about a minute) and creates the execution that runs it. Job must be running.

contactPhonestring
No format check here, so send E.164 anyway.
contactNamestring
contactEmailstring
contactMetadataobject

Send at least one contact field. An empty body is a 400: without a contact there is nothing to dispatch.

201 with contactId, the full contact row, jobId, status: "pending" and executionId: null. The execution id only exists once the scheduler dispatches; it reaches you as jobExecutionId on the webhook.

Prefer /v2/jobs/{id}/contacts for feeding contacts and /v2/jobs/{id}/execute for running. This one exists for integrations already using it.

On this page