Narrow pre-dial edits (schedule, metadata)
curl https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT \ --request PATCH \ --header 'Authorization: Bearer <token>' \ --header 'If-Match: <If-Match>' \ --header 'Content-Type: application/json' \ --data '{ "scheduling": { "window": { "not_before": "2026-08-30T09:14:22+02:00", "not_after": "2026-08-30T09:14:22+02:00" }, "local_call_times": [ { "days": [], "from": "09:00", "to": "09:00" } ], "max_attempts": 3, "retry": { "min_gap_hours": 24, "randomize_within_window": true }, "on_window_violation": "defer" }, "metadata": { "campaign": "q3-onboarding", "cost_center": "77" }}'requests.patch( "https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT", headers={ "Authorization": "Bearer <token>", "If-Match": "<If-Match>", "Content-Type": "application/json" }, json={ "scheduling": { "window": { "not_before": "2026-08-30T09:14:22+02:00", "not_after": "2026-08-30T09:14:22+02:00" }, "local_call_times": [ { "days": [], "from": "09:00", "to": "09:00" } ], "max_attempts": 3, "retry": { "min_gap_hours": 24, "randomize_within_window": True }, "on_window_violation": "defer" }, "metadata": { "campaign": "q3-onboarding", "cost_center": "77" } })fetch('https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT', { method: 'PATCH', headers: { Authorization: 'Bearer <token>', 'If-Match': '<If-Match>', 'Content-Type': 'application/json' }, body: JSON.stringify({ scheduling: { window: { not_before: '2026-08-30T09:14:22+02:00', not_after: '2026-08-30T09:14:22+02:00' }, local_call_times: [ { days: [], from: '09:00', to: '09:00' } ], max_attempts: 3, retry: { min_gap_hours: 24, randomize_within_window: true }, on_window_violation: 'defer' }, metadata: { campaign: 'q3-onboarding', cost_center: '77' } })})using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Patch, "https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "<token>");request.Headers.TryAddWithoutValidation("If-Match", "<If-Match>");request.Content = new StringContent("""{ "scheduling": { "window": { "not_before": "2026-08-30T09:14:22+02:00", "not_after": "2026-08-30T09:14:22+02:00" }, "local_call_times": [ { "days": [], "from": "09:00", "to": "09:00" } ], "max_attempts": 3, "retry": { "min_gap_hours": 24, "randomize_within_window": true }, "on_window_violation": "defer" }, "metadata": { "campaign": "q3-onboarding", "cost_center": "77" }}""",System.Text.Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);$ch = curl_init("https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer <token>', 'If-Match: <If-Match>', 'Content-Type: application/json']);curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'scheduling' => [ 'window' => [ 'not_before' => '2026-08-30T09:14:22+02:00', 'not_after' => '2026-08-30T09:14:22+02:00' ], 'local_call_times' => [ [ 'days' => [], 'from' => '09:00', 'to' => '09:00' ] ], 'max_attempts' => 3, 'retry' => [ 'min_gap_hours' => 24, 'randomize_within_window' => true ], 'on_window_violation' => 'defer' ], 'metadata' => [ 'campaign' => 'q3-onboarding', 'cost_center' => '77' ]]));
curl_exec($ch);
curl_close($ch);package main
import ( "fmt" "io" "net/http" "strings")
func main() { requestUrl := "https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT"
payload := strings.NewReader(`{ "scheduling": { "window": { "not_before": "2026-08-30T09:14:22+02:00", "not_after": "2026-08-30T09:14:22+02:00" }, "local_call_times": [ { "days": [], "from": "09:00", "to": "09:00" } ], "max_attempts": 3, "retry": { "min_gap_hours": 24, "randomize_within_window": true }, "on_window_violation": "defer" }, "metadata": { "campaign": "q3-onboarding", "cost_center": "77" }}`)
req, _ := http.NewRequest("PATCH", requestUrl, payload)
req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("If-Match", "<If-Match>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");RequestBody body = RequestBody.create(mediaType, "{\n \"scheduling\": {\n \"window\": {\n \"not_before\": \"2026-08-30T09:14:22+02:00\",\n \"not_after\": \"2026-08-30T09:14:22+02:00\"\n },\n \"local_call_times\": [\n {\n \"days\": [],\n \"from\": \"09:00\",\n \"to\": \"09:00\"\n }\n ],\n \"max_attempts\": 3,\n \"retry\": {\n \"min_gap_hours\": 24,\n \"randomize_within_window\": true\n },\n \"on_window_violation\": \"defer\"\n },\n \"metadata\": {\n \"campaign\": \"q3-onboarding\",\n \"cost_center\": \"77\"\n }\n}");Request request = new Request.Builder() .url("https://api.pacepayments.ai/v1/call-orders/ord_01J32K7M2QW9RT") .patch(body) .addHeader("Authorization", "Bearer <token>") .addHeader("If-Match", "<If-Match>") .addHeader("Content-Type", "application/json") .build();
Response response = client.newCall(request).execute();Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”PATCH /v1/call-orders/{id} - only before the first dial attempt.
Deliberately tiny. Everything that bears on the conversation is immutable after acceptance: a claim amount that changed between acceptance and the call would no longer be explicable in the result.
object
object
A window in the timezone of the person BEING CALLED, not ours.
object
Lokale Wanduhrzeit, 24 h, fuehrende Null.
Lokale Wanduhrzeit, 24 h, fuehrende Null.
object
Minimum gap between two attempts against the same person.
Scatters the redial instant within the permitted window, so the same person is not called at the same minute every day.
Only unreached attempts can trigger a retry. A conversation that actually took place is never a reason to call again.
What happens when your window and the permitted window do not intersect: defer moves the order into the permitted window (and the order may end up expired), reject refuses acceptance with a 422.
Your own opaque key-value pairs; mirrored on resources and in every event. CONTRACTUALLY free of personal data - Pace does not inspect the values. Whatever you put here falls outside the deletion and retention machinery that protects the rest of the order.
object
Responses
Section titled “Responses”Successful Response
object
object
A stable person key ON YOUR SIDE. It carries the suppression check, sequence deduplication and access/erasure requests - it MUST denote the same person across every order. An empty or reused value silently merges two people into one.
Everything the agent needs for this conversation.
object
object
object
An exact decimal, as a string - no float drift.
ISO 4217.
Itemisation of the claim.
object
The CREDITOR on whose behalf you are collecting - not your own name. Named to the debtor on first contact and whenever asked.
True when the claim carries an enforcement title (Mahnbescheid, Vollstreckungsbescheid, judgment). It changes what the agent may say about consequences and it extends the limitation period, so it is NEVER inferred.
The written statutory notice you have already sent.
It lets the agent REFER to that notice instead of improvising the disclosure. Whether your calls must carry the disclosure as well is your determination - this field is the record that you have provided it.
Earlier touches, newest last. Capped - send what matters, not half your CRM.
An earlier touch, on ANY channel.
The asymmetry with contacts is deliberate: sms, letter and whatsapp
are allowed here because they record what YOU have already done. contacts
does not know them, because Pace only makes calls. The agent uses the
history for tone and continuity (“we have already written to you twice”).
object
A window in the timezone of the person BEING CALLED, not ours.
object
Lokale Wanduhrzeit, 24 h, fuehrende Null.
Lokale Wanduhrzeit, 24 h, fuehrende Null.
object
Minimum gap between two attempts against the same person.
Scatters the redial instant within the permitted window, so the same person is not called at the same minute every day.
Only unreached attempts can trigger a retry. A conversation that actually took place is never a reason to call again.
What happens when your window and the permitted window do not intersect: defer moves the order into the permitted window (and the order may end up expired), reject refuses acceptance with a 422.
The decision corridor. The agent never goes beyond it.
object
object
The agent RECORDS THE WISH. It concludes nothing - the binding agreement is one you make afterwards, in writing. There is deliberately no second value.
object
Capped by your tenant retention rule - structured never delivers more than the tenant is allowed to retain.
Your own opaque key-value pairs; mirrored on resources and in every event. CONTRACTUALLY free of personal data - Pace does not inspect the values. Whatever you put here falls outside the deletion and retention machinery that protects the rest of the order.
object
The order-type version that applied at acceptance. Burned in, so the result stays interpretable after a configuration change.
Present on EVERY terminal order - including those with no conversation.
Exactly ONE place a client looks to see how an order turned out. result
is absent only while the order is still running.
object
The canonical summary - one value to branch on.
object
What was actually said to the debtor in THIS call.
Kept per call, not per order: the fields mirror the conversation, not the rulebook. An order nobody answered has nothing to report here - and should report nothing.
Attempts, oldest first.
object
object
Example
{ "subject": { "reference": "CUST-88213", "locale": "de-DE", "timezone": "Europe/Berlin" }, "contacts": [ { "channel": "phone" } ], "context": { "claim": { "outstanding": { "value": "129.90", "currency": "EUR" }, "original": { "value": "129.90", "currency": "EUR" }, "breakdown": { "principal": { "value": "129.90", "currency": "EUR" }, "interest": { "value": "129.90", "currency": "EUR" }, "dunning_fees": { "value": "129.90", "currency": "EUR" }, "collection_fees": { "value": "129.90", "currency": "EUR" }, "expenses": { "value": "129.90", "currency": "EUR" }, "already_paid": { "value": "129.90", "currency": "EUR" } }, "creditor_name": "Truman Textilien GmbH", "basis": { "description": "Jahresabo Textilpflege Premium, abgeschlossen am 12.06.2025" }, "titled": false }, "history": [ { "direction": "outbound" } ] }, "scheduling": { "local_call_times": [ { "days": [ "mon" ], "from": "09:00", "to": "09:00" } ], "max_attempts": 3, "retry": { "min_gap_hours": 24, "randomize_within_window": true }, "on_window_violation": "defer" }, "negotiation": { "installments": { "min_installment": { "value": "129.90", "currency": "EUR" }, "conclusion_mode": "record_wish_only" }, "settlement": { "conclusion_mode": "record_wish_only" } }, "delivery": { "transcript": "none", "include_recording_reference": false }, "metadata": { "campaign": "q3-onboarding", "cost_center": "77" }, "id": "ord_01J32K7M2QW9RT", "status": "accepted", "attempt_count": 0, "result": { "reachability": "reached", "engagement": "none", "termination": { "actor": "subject" } }, "compliance": { "recording": { "mode": "disabled" }, "contact_window_policy": "de_uwg7_default" }, "calls": [ { "disposition": "answered", "agent": { "id": "agt_lea_de_v4", "kind": "ai" } } ]}No valid access token. Client action: request a new token from the token endpoint and retry once. Repeated 401 with a fresh token means the client registration is disabled - contact Pace, do not retry in a loop.
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "code": "example", "detail": "example", "instance": "example", "trace_id": "example", "errors": [ { "pointer": "example", "code": "example", "message": "example" } ]}Authenticated but not permitted. insufficient_scope names the missing scope in detail; feature_not_enabled means the tenant lacks the feature; ip_not_allowlisted means the source IP is not on the client registration’s allowlist; simulate_not_allowed means a sandbox-only simulate block was sent to the live host. None of these are retryable.
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "code": "example", "detail": "example", "instance": "example", "trace_id": "example", "errors": [ { "pointer": "example", "code": "example", "message": "example" } ]}Validation Error
object
object
object
Examplegenerated
{ "detail": [ { "loc": [ "example" ], "msg": "example", "type": "example", "input": "example", "ctx": {} } ]}HTTP rate limit (rate_limited) or execution capacity refusal (quota_exceeded, backlog_full) - two distinct layers. Wait for Retry-After, then retry the identical request with the same Idempotency-Key. backlog_full will not clear in seconds; back off to minutes.
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "code": "example", "detail": "example", "instance": "example", "trace_id": "example", "errors": [ { "pointer": "example", "code": "example", "message": "example" } ]}Headers
Section titled “Headers”Seconds until the next attempt is permitted.
default
Section titled “default”Error (RFC 9457). Branch on code, never on title or detail.
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "code": "example", "detail": "example", "instance": "example", "trace_id": "example", "errors": [ { "pointer": "example", "code": "example", "message": "example" } ]}