The referral sandbox

At launchTest keys reach sandbox referrals: referrals you create and move through their lifecycle yourself. Nothing reaches a borrower, nothing is billed, and a live key never sees them.

Until the sandbox opens, a test key works with GET /api/gap/v1/me and the membership plan operations, and its referral and analytics calls are answered 403 test_key_referrals_unavailable. The simulate and attest operations below answer every call 404 operation_not_open until then.

Test keys

At launchA seat that manages credentials creates a test key on the portal's API & Webhooks page, after proving a fresh second factor. The form starts on a test key, which starts sa_test_ and lasts at most 90 days; a live key starts sa_live_. A live key that holds referrals.contact:read, as the Intake + status and Membership roster presets do, also needs an IP allowlist, set in the API console: once the partner security platform enforces, the console refuses one without it with 422 live_key_policy.

Until launch, the page creates live keys only. A legacy test key you already hold (sa_gap_test_) keeps working until the expiry GET /api/gap/v1/me reports: 90 days after it was created, or, for a key made before keys had an expiry, 90 days after we stamped it; we may schedule its retirement sooner, with notice. A legacy live key keeps working until we schedule its retirement, with notice.

Use made-up borrowers

The sandbox is for invented data only. Make up the borrower and the vehicle, use an example.com email address and a 555 phone number, and never enter a real borrower's details.

Create a sandbox referral

Send POST /api/gap/v1/referrals with a test key, as in the quickstart. Idempotency keys are kept per mode: the same key sent with a live key and a test key makes two referrals. A live key can't send a key that starts with test:. Start your test requests' Idempotency-Keys with it, and a test request sent with a live key by mistake is refused with 409 idempotency_key_mode_conflict instead of creating a real referral.

Move it along its lifecycle

POST /api/gap/v1/referrals/{id}/simulate moves one of your sandbox referrals one step, with to set to one of: invited, activated, in_progress, settled, closed, declined, unreachable, expired. A step off the lifecycle is 409 invalid_transition, and a live key gets 403 simulate_requires_test_key. A referral whose borrower withdrew permission to report its progress is 409 reporting_withdrawn, as every write to it is.

Request
curl -X POST https://secondappraisal.com/api/gap/v1/referrals/clqz8k2p70001ab2cd3ef4gh6/simulate \
  -H "Authorization: Bearer $SECONDAPPRAISAL_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "invited" }'

A step to settled takes the figures to settle with; the uplift and the exposure figures are computed from them as for a live settlement:

Body of a step to settled
{
  "to": "settled",
  "outcome": {
    "appraised_value_cents": 2690000,
    "final_settlement_cents": 2640000
  }
}

Sandbox webhooks

Each webhook endpoint is live or test. A simulated step sends the event a live referral sends at that step to your test endpoints only, with livemode: false, signed the same way, so the verification code you test is the code you ship.

Warm handoffs

A warm-handoff referral created without its disclosure waits for POST /api/gap/v1/referrals/{id}/attest. A test key attests its sandbox referrals, and no outreach is opened for them.