Skip to main content
POST
/
addresses
Create Address
curl --request POST \
  --url https://api.zopay.cash/connect/v1/addresses \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "asset": "<string>",
  "network": "<string>",
  "external_ref": "<string>",
  "label": "<string>"
}
'
{}
Mint a deposit address. Two modes:
  • external_ref set — mint a per-user address. The partner-user’s profile is lazy-provisioned on first sight.
  • external_ref absent — mint a tenant-treasury address (pooled / no per-user attribution). Response omits external_ref.
Idempotency: the Idempotency-Key header is required for this endpoint (enforced by idempotency_required). Same key + same body within 24h replays the original response verbatim — partner retries are safe. Same key + different body returns 409 idempotency_conflict. Beneath the Connect-side idempotency the underlying AddressService.ensure_primary_address is itself idempotent on (user, asset, network) via a Postgres advisory lock. Two paths to the same address therefore converge whether the partner sends the Idempotency-Key or not — the header is the cleaner contract, the lock is the safety net. Note idem is taken before auth in the dependency order above so the Idempotency-Key header is parsed (which can 400 on its own) before the DB hit for the approval gate. Both happen long before we touch BitGo / Rhino. Sandbox routing: sk_test_… keys (auth.mode == "sandbox") are routed to ConnectAddressesSandboxService, which makes no downstream calls and returns a deterministic fake address. This is the compliance-relevant boundary — the single point in the codebase where sandbox traffic is prevented from reaching real custody infrastructure. sk_live_… keys continue to hit the real path.

Authorizations

Authorization
string
header
required

Paste your Connect API key (sk_live_… for production, sk_test_… for sandbox) without the Bearer prefix. Mint and rotate keys from the admin panel.

Headers

Idempotency-Key
string | null
authorization
string | null

Body

application/json

Request body for POST /connect/v1/addresses.

Two modes, switched on the presence of external_ref:

  • external_ref set → mint a deposit address for that partner-user (lazy-provisioning the underlying profile + mapping on first sight).
  • external_ref absent → mint a tenant-treasury / pooled address (no per-user attribution).

The partner-facing semantics are identical in both modes; the only difference is whether the response echoes external_ref.

Forbidden extras: typo'd field names surface as a 422 rather than being silently ignored. Partners can recover by checking their request body shape against the docs.

asset
string
required

Asset code (USDT, XAUT). Case-insensitive.

Required string length: 2 - 16
network
string
required

Network code (solana, ethereum). Case-insensitive.

Required string length: 2 - 16
external_ref
string | null

Partner's user identifier. Omit to mint a tenant-treasury address (no per-user attribution).

Maximum string length: 255
label
string | null

Optional partner-supplied label persisted on the address row for the partner's own records.

Maximum string length: 255

Response

Successful Response

The response is of type Response Create Address Addresses Post · object.