Skip to content

Environments

Two environments. They do not share credentials, they do not share data, and the sandbox never places a real telephone call.

Live Sandbox
API host https://api.pacepayments.ai https://sandbox.api.pacepayments.ai
Token host https://auth.pacepayments.ai https://auth.pacepayments.ai
Credentials Live client registration Separate sandbox registration
Telephony Real calls, real people Simulated - no call is placed
simulate block 403 simulate_not_allowed Accepted
Data Production tenant data Its own data space

Every event carries environment. Check it before you process a webhook.

if event["environment"] != MY_ENVIRONMENT:
return 200 # acknowledge, then ignore

This looks redundant until the day someone points a sandbox endpoint at a production handler, or copies a URL between two configuration files. When that happens, the consequence is a simulated payment promise written into a real case file - and nothing about the payload would otherwise tell you it was not real. Acknowledge the delivery so Pace does not retry it, then drop it.

GET /v1/tenant returns your own environment value, so a service can learn which one it is in at startup rather than being told through a build flag that may be wrong.

The sandbox does not fabricate results. It writes exactly the same records a real call writes when it hangs up, and then runs the same derivation over them that production runs. There is no second result producer.

That distinction is not academic. A simulator that assembled Result objects would only ever test the simulator. This one tests the derivation that also runs live - and during its first run it surfaced three defects in the live path that no unit test had caught.

What it means for you: a result you receive in the sandbox has the same shape, the same fields and the same edge cases as a live one. Writing your handler against the sandbox is time well spent.

Everything simulated is marked simulated: true internally and its call identifier begins with SIMUL. You will not normally see those markers - they exist so that Pace’s own analytics stay honest.

The first attempt lands on the next quarter-hour boundary. Dial scheduling rounds up to a fifteen-minute grid, in the sandbox as in production, so an order you submit at 09:07 will not be attempted before 09:15. Budget for it in a test script rather than assuming something is broken.

busy is not offered. It appears in the CallDisposition registry, but the live path maps a busy signal onto no_answer and never produces the value. A sandbox that handed you busy would invite you to write retry_on: ["busy"] - green in test, dead in production. See Sandbox testing.

There are no test clocks. You cannot fast-forward a retry window or a wait step. Long waits have to be tested with short durations.

  1. Separate credentials, separate stores

    Sandbox and live secrets should not live in the same vault path. A copy-paste between two entries in the same file is the failure this prevents.

  2. Separate webhook endpoints

    Register the sandbox URL on the sandbox host only. A single endpoint receiving both streams is one environment check away from a bad day.

  3. Assert the environment at startup

    Read GET /v1/tenant and compare it against what your deployment believes. Refuse to start on a mismatch - that is far cheaper than discovering it later in a case file.