StatusPrivate betaPublic testnets — test tokens, no real valueMainnet rolls out per jurisdiction

Authentication

Authentication

Every request to /api/v1/merchant is authenticated with a secret API key, sent as a Bearer token in the Authorization header.

Secret API keys

Keys come in two environments, distinguished by their prefix. Use the test key against Base Sepolia while you integrate, and the live key once you go to mainnet.

PrefixEnvironmentSettles on
rsend_test_…TestBase Sepolia testnet (test tokens, no real value)
rsend_live_…LiveMainnet — enabled per jurisdiction as RSends rolls out
Authorization header
curl https://pay.rsends.io/api/backend/api/v1/merchant/transactions \
  -H "Authorization: Bearer rsend_test_YOUR_KEY"

How keys are issued

Keys are self-serve. Sign in, open /app → API keys → Merchant keys and create one. You need the admin role in your organisation. Every key minted this way is rsend_test_…, scoped write, and bound to the test environment; live keys are issued as mainnet is enabled for your jurisdiction. You can hold up to 5 active keys per environment — a sixth returns 409 max_keys_reached. Revoking is immediate and idempotent.

Shown once, hashed at rest

The full secret is shown to you once, at creation. RSends stores only a bcrypt hash plus a short display prefix — it cannot recover or re-show the key. If you lose it, revoke it and mint a new one. Treat it like a password: server-side only, never in client code or a repo.

One prerequisite: your company profile

Before you can mint a key you have to submit your organisation's company profile, in /app. It is a single self-serve form — nobody has to approve you to use the sandbox. Submit it and testnet access is immediate.

FieldNotes
legal_nameRegistered company name
countryCountry of registration
registration_numberCompany registration number
tax_or_vat_numberTax or VAT number
business_categoryWhat the business does
expected_monthly_volumeRough band, not a commitment
countries_servedWhere your customers are
primary_stablecoinThe token you expect to settle in
declarationsTwo must be affirmed (no sanctioned countries, no prohibited activities) plus a PEP disclosure. trading_name and website are optional.

Until it is submitted, every /api/v1/merchant/* call returns 403 — with a valid key, too. That is the first thing to check when a fresh integration answers 403 to everything.

403 — profile not submitted yet
{ "detail": { "code": "company_profile_required" } }

// If your organisation was explicitly declined:
{ "detail": { "code": "approval_declined", "reason": "…" } }

Going live is where a human looks

Manual approval still applies to mainnet: a rsend_live_ key requires an approved organisation, and the same call with a live key returns 403 approval_pending until that happens. The sandbox deliberately does not wait on anyone — it settles faucet tokens on a testnet.

Scopes & environments

Each key is bound to a single environment (test or live) and a scope. Enforcement is by HTTP method: any non-GET request made with a read key is rejected with 403 INSUFFICIENT_SCOPE. A read-only key can pull reporting data but cannot create intents.

ScopeGrants
readGET only — payment intents, transactions and reporting
writeEverything read does, plus create/cancel/resolve intents and manage webhooks. This is what self-serve keys get
adminEverything write does. Not self-provisionable

The environment binding is enforced on both reads and writes: a test key creating an intent on a mainnet chain gets 400 TESTNET_ONLY, and a live key on a testnet chain gets 400 MAINNET_ONLY. Test and live data never mix — that includes webhook deliveries.

Retrying safely

Send an X-Idempotency-Key header on any POST and a retry with the same key replays the original response instead of re-running the operation. The record is kept for 24 hours, and it is scoped to your account and environment — no other merchant's key can collide with yours. Resend the original body unchanged: the same key with a different body is 409 IDEMPOTENCY_KEY_REUSED. A retry that arrives while the first request is still in flight gets 409 DUPLICATE_REQUEST_IN_FLIGHT. See Errors.

Authentication errors

A missing, malformed, or revoked key returns 401 with INVALID_API_KEY. See Errors for the full table.

GET/api/v1/merchant/transactions