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>"
}
'import requests
url = "https://api.zopay.cash/connect/v1/addresses"
payload = {
"asset": "<string>",
"network": "<string>",
"external_ref": "<string>",
"label": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
asset: '<string>',
network: '<string>',
external_ref: '<string>',
label: '<string>'
})
};
fetch('https://api.zopay.cash/connect/v1/addresses', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.zopay.cash/connect/v1/addresses",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'asset' => '<string>',
'network' => '<string>',
'external_ref' => '<string>',
'label' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.zopay.cash/connect/v1/addresses"
payload := strings.NewReader("{\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"external_ref\": \"<string>\",\n \"label\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.zopay.cash/connect/v1/addresses")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"external_ref\": \"<string>\",\n \"label\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zopay.cash/connect/v1/addresses")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"external_ref\": \"<string>\",\n \"label\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"asset": "<string>",
"network": "<string>",
"address": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"external_ref": "<string>",
"memo": "<string>"
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}Create Address
Mint a deposit 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>"
}
'import requests
url = "https://api.zopay.cash/connect/v1/addresses"
payload = {
"asset": "<string>",
"network": "<string>",
"external_ref": "<string>",
"label": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
asset: '<string>',
network: '<string>',
external_ref: '<string>',
label: '<string>'
})
};
fetch('https://api.zopay.cash/connect/v1/addresses', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.zopay.cash/connect/v1/addresses",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'asset' => '<string>',
'network' => '<string>',
'external_ref' => '<string>',
'label' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.zopay.cash/connect/v1/addresses"
payload := strings.NewReader("{\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"external_ref\": \"<string>\",\n \"label\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.zopay.cash/connect/v1/addresses")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"external_ref\": \"<string>\",\n \"label\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zopay.cash/connect/v1/addresses")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"asset\": \"<string>\",\n \"network\": \"<string>\",\n \"external_ref\": \"<string>\",\n \"label\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"asset": "<string>",
"network": "<string>",
"address": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"external_ref": "<string>",
"memo": "<string>"
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}{
"error": {
"type": "invalid_request_error",
"code": "authentication_required",
"message": "Missing or malformed Authorization header. Send: Authorization: Bearer sk_live_... or sk_test_...",
"doc_url": "https://docs.zopay.cash/errors/authentication_required",
"param": "currencies"
}
}external_refset — mint a per-user address. The partner-user’s profile is lazy-provisioned on first sight.external_refabsent — mint a tenant-treasury address (pooled / no per-user attribution). Response omitsexternal_ref.
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
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
Body
Request body for POST /connect/v1/addresses.
Two modes, switched on the presence of external_ref:
external_refset → mint a deposit address for that partner-user (lazy-provisioning the underlying profile + mapping on first sight).external_refabsent → 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 code (USDT, XAUT). Case-insensitive.
2 - 16Network code (solana, ethereum). Case-insensitive.
2 - 16Partner's user identifier. Omit to mint a tenant-treasury address (no per-user attribution).
255Optional partner-supplied label persisted on the address row for the partner's own records.
255Response
Successful Response
A single deposit-address row in the partner-facing shape.
Opaque partner-stable identifier (e.g. addr_VVNEVDpzb2xhbmE6RWhKO...). Pass to GET /addresses/:id to retrieve this row again.
Asset code, uppercase (USDT, XAUT).
Network code, lowercase (solana, ethereum).
On-chain wallet address. Partner shares this with the user.
The partner's user id this address belongs to. Absent (key omitted from the JSON, not null) when the address is a tenant-treasury / pooled address minted by calling POST /addresses without external_ref.
Memo / destination tag for chains that require one (XRP, XLM, COSMOS). NULL on chains that don't.