Skip to content

Test your integration ​

Exercise every path your integration handles — success and failure — on staging, before you go live.

New to the API? Walk Get started first; this page assumes you have.

Requirements ​

RequirementDescription
Staging credentialsAsk your Zay contact in your shared Slack channel
A phone and an inboxFor signing in as test users — any country's phone number works
A webhook endpointYour real handler, deployed somewhere public over HTTPS

How staging differs from production ​

StagingProduction
Hostsapi-connect.zay.me, privy-stag.zay.meapi.zay.me, privy.zay.me
Identity verificationSandbox — accepts any details, with a pass / fail toggle on screenReal verification
NetworkBase SepoliaBase
Payout confirmationNot live yet — every payout expires after 48 hoursNot live yet — every payout expires after 48 hours
CredentialsSeparateSeparate

See How payouts work.

Onboarding scenarios ​

Create a user, open their onboarding_url, and steer the flow:

To testDo thisYou receive
A user who finishesPick United States, set the verification toggle to pass, then wait for the carduser.onboarding_started, user.kyc_passed, then user.onboarding_completed with wallet_address
Failed verificationSet the toggle to failuser.onboarding_failed with a reason; the user stays onboarding
An unsupported countryPick any country but the United StatesNo completion event. The user lands on a waitlist screen, and your callback_url gets status=residence_country_waitlisted
A user who stops halfwayClose the tab after the phone step, then open the same onboarding_url againThe user resumes where they stopped
The return to your productAdd a callback_url and finish the flowA redirect to it with ?status=… — see Onboard a user

Each user needs its own phone number and external_id, so keep a few numbers you can receive SMS on, or reuse a user who already finished.

Payout scenarios ​

To testDo thisYou receive
An expired payoutReport a payout — any hashpayout.expired with reason deposit not confirmed within the verification window — after 48 hours
A safe retrySend the same report twice with the same Idempotency-Key, within 30 secondsThe same payout back, once — see Report a payout
ValidationReport "amount": "0", or omit transaction_hash422 with the field in errors

An expired payout takes 48 hours to arrive, and a received one cannot arrive until confirmation is live. To test your payout.expired and payout.received handlers sooner, feed them the example payloads from the Event catalog, signed the way Receive and verify webhooks describes.

Webhook scenarios ​

Use Trigger test delivery to send webhook_endpoint.test on demand:

To testDo thisWhat happens
VerificationTrigger a test deliveryYour handler verifies the signature and answers 2xx
DuplicatesTrigger it, answer 500 once, then 2xxZay retries with the same webhook-id; your handler processes it once
A forged eventSend your endpoint a request with a wrong webhook-signatureYour handler rejects it with 400
An unknown event typeSend your endpoint a signed event with an invented typeYour handler ignores it and answers 2xx

Don't answer 410 unless you mean it: it disables the endpoint at once. Re-enable it with Update webhook endpoint.

Request scenarios ​

To testDo thisYou receive
A signing bugSign with the wrong key401 with string_to_sign_bytes — see Sign requests
Clock driftSend a zay-timestamp 10 minutes old401 Request timestamp outside allowed drift of 5 minutes
Rate limitsSend more than 100 requests in a minute to one resource429 — see Handle errors and retries

Check the result ​

You're ready for Go live when, on staging:

  • a user finished onboarding and you received their user.onboarding_completed;
  • a payout you reported was accepted, and your handlers process payout.received and payout.expired;
  • your handler verifies signatures and processes a retried event only once.