Platform Runs API
Platform Runs are the business-facing batch operations of the quote-to-cash pipeline, exposed as first-class objects: Mediation Run, Usage Rating Run, Rated Transaction Run, Invoice PDF Run, Payment Run, Dunning Run, Journal Run, and multi-stage sequences such as the Re-rating Sequence. Each run wraps one or more job executions behind a single status machine, so you launch and follow a named business operation instead of driving raw job instances.
Billing Runs are the exception: they were already a first-class resource and
keep their dedicated endpoints at /api/v1/billingRuns. The run catalog points
there.
Prerequisites
A bearer token, per Authentication:
export TOKEN=$(curl -s -X POST "$KEYCLOAK_TOKEN_URL" \
-d "grant_type=client_credentials&client_id=$KEYCLOAK_CLIENT_ID&client_secret=$KEYCLOAK_CLIENT_SECRET" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
The run catalog
GET /api/v1/runs/catalog returns every run type with its display name,
category, ordered stages, parameter schema, and execution mode. The catalog is
the single source of truth: build launch forms and run pages from it rather
than hardcoding run types.
curl -s -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/runs/catalog" | jq '.[0]'
{
"key": "MEDIATION",
"displayName": "Mediation Run",
"description": "Convert collected CDRs into rateable usage events (EDRs).",
"category": "MEDIATION",
"executionMode": "ON_DEMAND",
"launchable": true,
"sequence": false,
"stages": [
{ "key": "MEDIATION", "jobTemplate": "MediationJob", "jobInstanceCode": "RUN_MEDIATION" }
],
"params": []
}
Two fields drive client behavior:
executionMode:MANAGEDruns (for example Recurring Rating) are scheduled by the platform and never need a manual launch;ON_DEMANDruns are launched by an operator or an integration.dedicatedResource: when set (theBILLINGentry points to/api/v1/billingRuns), the type is catalog-only here and must be driven through its own resource.
Launching a run
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "runType": "RATED_TRANSACTIONS", "description": "Convert open wallet operations" }' \
"$BASE_URL/api/v1/runs"
The call returns 202 Accepted with the created run. Execution is
asynchronous: poll GET /api/v1/runs/{code}.
{
"code": "RUN-3",
"runType": "RATED_TRANSACTIONS",
"status": "RUNNING",
"origin": "AD_HOC",
"steps": [
{
"position": 0,
"stageRunType": "RATED_TRANSACTIONS",
"status": "RUNNING",
"jobInstanceCode": "RUN_RATED_TRANSACTIONS",
"jobExecutionId": 2099
}
]
}
Error contract:
| Status | Meaning |
|---|---|
409 | A run of this type is already pending or running |
422 | Unknown run type, catalog-only type (BILLING), or invalid parameters |
400 | Missing runType |
Run statuses
PENDING → RUNNING → COMPLETED | COMPLETED_WITH_ERRORS | FAILED |
CANCELLED. COMPLETED_WITH_ERRORS means the run finished but one or more
items were rejected (the counters carry the detail). A failed or cancelled step
cancels the remaining steps of a sequence.
Sequences
A sequence executes several stages in order; the platform advances the chain as each stage completes. The Re-rating Sequence is a built-in example:
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "runType": "RE_RATING" }' "$BASE_URL/api/v1/runs"
{
"code": "RUN-4",
"status": "COMPLETED",
"steps": [
{ "stageRunType": "RATING_CANCELLATION", "status": "COMPLETED", "jobExecutionId": 2100 },
{ "stageRunType": "DUPLICATE_BILLED_RTS", "status": "COMPLETED", "jobExecutionId": 2101 },
{ "stageRunType": "RE_RATING_V2", "status": "COMPLETED", "jobExecutionId": 2102 }
]
}
INVOICE_CYCLE (rated transactions → invoice lines → invoicing → XML → PDF)
and BILL_TO_CASH (the full pipeline through payment) ship as launchable
presets. By default a sequence continues past a stage that completed with item
errors; a failed stage always stops it.
History and follow-up
# Paginated history, filterable by runType, status, origin
curl -s -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/runs?runType=RE_RATING&status=COMPLETED&limit=20&offset=0"
# One run, with live counters while a step is running
curl -s -H "Authorization: Bearer $TOKEN" "$BASE_URL/api/v1/runs/RUN-4"
Each step links to its jobExecutionId, so drill-down to the technical job
execution history stays one hop away.
When a run fails: understand, then resume
A run can end three ways short of success, and each is visible on the ticket:
COMPLETED_WITH_ERRORS: the run finished but some items were rejected. The counters carry the split; per-item reasons live in the linked job execution report. Rejected items stay pending, so the next run of the same type picks them up once the cause is fixed. Relaunch is the right action here.FAILED: a step crashed. The run stores the engine's error message (errorMessage), the failed step is marked, and later steps are cancelled.CANCELLED: an operator stopped it; unstarted steps were cancelled.
For FAILED and CANCELLED runs, resume instead of relaunching:
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/runs/RUN-12/resume"
202 returns a follow-up run linked through resumedFrom. Steps that
completed in the original are carried over as completed, keeping their
execution links; execution restarts at the first step that never finished.
{
"code": "RUN-13",
"resumedFrom": "RUN-12",
"status": "RUNNING",
"steps": [
{ "stageRunType": "RATING_CANCELLATION", "status": "COMPLETED", "jobExecutionId": 2100 },
{ "stageRunType": "DUPLICATE_BILLED_RTS", "status": "RUNNING", "jobExecutionId": 2118 },
{ "stageRunType": "RE_RATING_V2", "status": "PENDING" }
]
}
This is safe by construction: every pipeline stage only processes items still
waiting (unrated events, unbilled transactions, invoices without documents), and
progress is committed in batches as a run advances. Nothing is rated or billed
twice on resume. Error contract: 404 unknown run, 409 another run of the
type is active, 422 the run is still active or completed all its steps.
Automatic runs: retry once, then alert
Scheduled (managed) runs do not depend on anyone watching. When one fails, the
platform retries it once automatically after a short delay (default 15 minutes,
run.autoRetry.delayMinutes). The retry is a resume, so it continues from where
the failure stopped. If the retry also fails, the platform raises an alert
rather than failing silently, and does not retry again.
Two fields on the run expose this:
autoRetry: true when the run was created by the automatic retry (not a manual resume).retryState:NONE,RETRIED(this failed run already spawned its one automatic retry), orALERTED(a failed automatic retry that needs attention).
The always-on alert is the run's ALERTED state, which the Automations screen
shows in red, plus an error log entry. When a recipient is configured through
run.alert.recipient, an email is also sent. A successful retry leaves no alert.
Cancelling
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/runs/RUN-4/cancellation"
202: pending steps are cancelled immediately; a running step is asked to stop
through the job engine and the run reaches CANCELLED once the engine
confirms. Cancelling a finished run returns 422.
Runs vs jobs
The job engine (job instances, timers, Job Studio chains) stays available under
Administration for technical work: scripting jobs, file imports, purges. The
run layer never modifies it. Canonical run instances are prefixed RUN_ and
are owned by the platform; operator-managed instances (for example M_Job,
U_Job) keep working independently.