Skip to content

Going live

The difference between sandbox and live is that a real person answers. This checklist is ordered by what goes wrong most expensively.

Environment separation is enforced, not intended
  • Live and sandbox credentials live in different vault paths, not two entries in one file.
  • Your service reads GET /v1/tenant at startup and refuses to start if environment disagrees with its own configuration.
  • Your webhook handler checks event.environment on every delivery and drops mismatches with a 200.

A simulated payment promise written into a real case file is not recoverable by reading the payload - nothing else in it says it was not real.

Webhook signature verification is complete
  • Verified against the raw body bytes, not re-serialised JSON.
  • Timestamp tolerance enforced - 300 seconds.
  • All v1 values in the header are collected and checked, not just the first. Code that checks only the first works for 24 hours after a rotation, then stops.
  • Constant-time comparison.
  • Tested end to end with POST /v1/webhook-endpoints/{id}/test.

See Receiving results.

Idempotency keys survive a restart
  • Generated where the work is decided, not in the HTTP wrapper.
  • Persisted with the work item, so a crash mid-retry does not lose the key.
  • Reused across every retry of the same logical request, including timeouts.

A key that only exists in memory is gone exactly when you need it.

Suppression handling is treated as normal, not exceptional
  • 422 subject_suppressed marks the case and moves on. It does not page anyone.
  • You subscribe to suppression.* - it is not in the default subscription.
  • An in-call objection stops further contact on your side too, through every channel you run.

The suppression exists before call_order.completed reaches you, so by the time you read the result the person is already blocked here.

Transcripts you may need are copied on arrival
  • Your result handler copies the transcript into your own case file when the result arrives, not on demand later.
  • expires_at is respected - seven days by default, then 404.

There is no recovery endpoint. If a dispute surfaces in month three, the transcript is either in your system or it is gone.

Unknown values degrade instead of throwing
  • Unknown summary_code → your “other” bucket.
  • Unknown outcomes[].type → ignored, not fatal.
  • Unknown event type → 200 and move on.
  • Unexpected fields → tolerated.

These registries are open and grow without a version bump. A strict client breaks on a Tuesday for no reason it can see.

Retry logic distinguishes the four cases
  • Timeout → retry with the same key.
  • 429/5xx → retry, honouring Retry-After.
  • 401 → one fresh token, then stop.
  • 403/404/409/422 → never retry.

See Handling errors.

Why it matters
Verification mode Decides which subject fields are mandatory. name_address also needs the postcode. Read it from GET /v1/tenant.
Order types and conversation profiles Which keys exist for you, and which agent behaviour each binds.
Quotas max_concurrent_calls, max_dials_per_day, max_contacts_per_subject_per_day. They start deliberately conservative and are raised after the first supervised campaign - read them at runtime rather than hard-coding.
Calling hours Your tenant’s configured window, which narrows the statutory one.
Retention transcript_mode, transcript_retention, result_months.
Egress addresses If you allowlist inbound webhook traffic. These are provisional - confirm before relying on them.
  1. Watch for endpoint self-disabling

    An endpoint is disabled after 200 consecutive failures or 5 days of unbroken failure. The notification email is not wired up yet, so subscribe webhook_endpoint.* on a second endpoint or poll GET /v1/webhook-endpoints from a monitoring job. This failing silently is the scenario to avoid.

  2. Reconcile against the feed on a schedule

    A nightly job comparing GET /v1/events against what you processed will catch a dead-lettered delivery the same day rather than the same quarter. The feed is complete - it is written before delivery is attempted - so it is a genuine reconciliation path.

  3. Track RateLimit headers before you need them

    They are on every response, not only 429s. Graphing RateLimit-Remaining tells you about a throughput problem before it becomes an incident.

  4. Plan the first secret rotation

    Rotate once in the sandbox before you have to do it live. Both webhook secrets sign for 24 hours; both client secrets authenticate until the old one is revoked. Neither needs an outage - but you want to have done it once.

Point at production with a narrow first batch - a handful of cases you have chosen, with max_attempts: 1 and a window you are watching in person.

The sandbox verifies your integration. It cannot verify that your case data is right, that the creditor name reads well when spoken aloud, or that the claim description is one a debtor recognises. Those only show up in real conversations, and the cheapest place to find them is a batch small enough to read every result by hand.

These are current behaviour, not roadmap. Design for them:

  • Recording is off platform-wide. GET /v1/calls/{id}/recording returns 404.
  • compliance.statutory_disclosure is always empty. Do not build a compliance report on it.
  • busy does not occur. A busy signal is reported as no_answer.
  • Sequence execution is not yet live. The call step inside a ladder and the sharp exit conditions are coming. Model A is complete.
  • No access or erasure endpoint. Those requests run through Pace support, and subject.reference is what makes them answerable.
  • No batch submission. Submit orders in a loop, respecting rate limits.
  • No SDKs. The API reference generates working snippets in seven languages.
  • Quota enforcement (quota_exceeded, backlog_full) is not yet active. Handle the codes now; they will appear without an API version change.

Questions that this documentation does not answer, and anything that needs a documented override - deleting an in-call objection, an access or erasure request - go to Pace support rather than through the API.