Transfer API
- 服务地址
https://transfer-api.psp.example.comExample host; obtain the actual Transfer host from PSP- 认证
- Ed25519 签名
- 版本
- 1.0.0
- OpenAPI
- 下载规范
Transfer service surface for merchant disbursement write flows. This service only accepts transfer account secrets and rejects invoice/query/webhook/proof traffic. A missing X-API-ID header returns 400 INVALID_REQUEST. A missing X-API-Key header or invalid credentials return 401 UNAUTHORIZED. A credential store failure returns 500 INTERNAL_ERROR before the request handler runs.
Transfers
Section titled “Transfers”Create a transfer intent
Section titled “Create a transfer intent”Requires a transfer account secret and transfers:write scope.
Send the idempotency key in X-Idempotency-Key or Idempotency-Key;
at least one is required. When both are sent they must be equal,
otherwise the request is rejected with 400 INVALID_REQUEST. The Ed25519
signature covers X-Idempotency-Key when it is sent, otherwise
Idempotency-Key.
The same header key is also the transfer’s business idempotency key: reusing it for a different transfer request is rejected with 409 CONFLICT. The request body has no separate idempotency field.
请求头
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
X-API-Key |
string | 必填 | — |
X-Timestamp |
string | 必填 | — |
X-Signature |
string | 必填 | — |
X-Idempotency-Key |
string | 可选 | Idempotency key. Send it in this header or in Idempotency-Key; at least one of the two is required. When this header is sent, the Ed25519 signature covers its value. If both headers are sent they must be equal, otherwise the request is rejected with 400 INVALID_REQUEST. · 最短 1 |
Idempotency-Key |
string | 可选 | Idempotency key, alternative to X-Idempotency-Key; at least one of the two is required. The Ed25519 signature covers this header only when X-Idempotency-Key is not sent. If both headers are sent they must be equal, otherwise the request is rejected with 400 INVALID_REQUEST. · 最短 1 |
请求体 application/json · 必填
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
payment_method |
enum | 必填 | 可选值:pix、spei、upi、america_ach、paypal、chime、zelle、cash_app、venmo、emt、apple_pay |
rail_variant |
string | 必填 | Canonical rail variant paired with payment_method. |
amount |
integer<int64> | 必填 | ≥ 1 |
currency |
string | 必填 | 最短 3 · 最长 3 |
beneficiary |
object | 可选 | — |
beneficiary.name |
string | 可选 | 最长 200 |
beneficiary.tax_id |
string | 可选 | 收款人证件号。账户 transfer_beneficiary_validation_mode 为 optional 或 required 且提交了本字段时,须符合账户市场格式:巴西 CPF(11 位数字含校验位)或 CNPJ (14 位,数字或字母数字,含官方校验位,例如 00.000.000/E08G-12);墨西哥 RFC (12 或 13 位,日期段月份 01–12、日期 01–31)。格式错误返回 INVALID_REQUEST。 required 档未提交亦返回 INVALID_REQUEST。 · 最长 50 |
beneficiary.email |
string<email> | 可选 | 最长 200 |
beneficiary.phone |
string | 可选 | 最长 50 |
beneficiary.account |
string | 可选 | 最长 200 |
beneficiary.bank_code |
string | 可选 | 最长 20 |
beneficiary.branch_code |
string | 可选 | 最长 20 |
instruction |
object | 可选 | PIX QR may omit beneficiary; other transfer modes require beneficiary name and account. PIX and SPEI consume instruction.tax_id. It must be a string; a number or object returns INVALID_REQUEST. UPI, ACH, and hosted methods ignore this field and do not persist it as beneficiary.tax_id. When transfer_beneficiary_validation_mode is optional or required and the value is non-empty, it must match the account market format (Brazil CPF, numeric or alphanumeric CNPJ, or Mexico RFC) and must match beneficiary.tax_id when that field is also set. Off mode does not send the value upstream. PIX keeps an instruction-only tax_id off beneficiary.tax_id so older Gateway versions can replay the same request. SPEI likewise keeps an explicit RFC and an instruction-only alias off beneficiary.tax_id. Off mode does not backfill the channel RFC from beneficiary.tax_id or instruction.tax_id; an explicit instruction.beneficiary_rfc is still submitted unchanged. Optional and required modes persist the RFC decision for the channel and worker. SPEI beneficiary_rfc must be a string. When transfer_beneficiary_validation_mode is optional or required and this field is non-empty (including when beneficiary.tax_id is omitted), it must be a Mexican RFC (12 or 13 characters, month 01–12, day 01–31); otherwise the request returns INVALID_REQUEST. |
description |
string | 可选 | 最长 500 |
merchant_order_id |
string | 可选 | 最长 100 |
webhook_url |
string<uri> | 可选 | 最长 500 |
metadata |
object | 可选 | — |
请求示例
curl -X POST 'https://transfer-api.psp.example.com/api/v1/payments/transfers' \ -H 'X-API-Key: <api-key>' \ -H 'X-Timestamp: <timestamp>' \ -H 'X-Signature: <signature>' \ -H 'X-API-ID: <api-id>' \ -H 'Content-Type: application/json' \ -d '{ "payment_method": "pix", "rail_variant": "pix_key", "amount": 1, "currency": "string", "beneficiary": { "name": "string", "tax_id": "string", "email": "[email protected]", "phone": "string", "account": "string", "bank_code": "string", "branch_code": "string" }, "instruction": {}, "description": "string", "merchant_order_id": "string", "webhook_url": "https://example.com", "metadata": {} }'响应
Transfer intent created
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id |
string<uuid> | 必填 | — |
transfer_number |
string | 必填 | — |
payment_method |
string | 必填 | — |
classification |
object | 必填 | — |
classification.classification_status |
enum | 必填 | 可选值:resolved |
classification.payment_category |
string | 必填 | — |
classification.payment_method |
string | 必填 | — |
classification.rail_variant |
string | 必填 | — |
amount |
integer<int64> | 必填 | — |
currency |
string | 必填 | — |
transferred_amount |
integer<int64> | 可选 | — |
returned_amount |
integer<int64> | 可选 | — |
status |
enum | 必填 | 可选值:pending、processing、completed、failed、returned、canceled |
state |
string | 可选 | — |
description |
string | 可选 | — |
merchant_order_id |
string | 可选 | — |
provider_transaction_id |
string | 可选 | — |
beneficiary |
object | 可选 | The beneficiary the merchant submitted and PSP sent upstream. Echoed back unchanged; a provider callback never overwrites it. |
beneficiary.name |
string | 可选 | 最长 200 |
beneficiary.tax_id |
string | 可选 | 收款人证件号。账户 transfer_beneficiary_validation_mode 为 optional 或 required 且提交了本字段时,须符合账户市场格式:巴西 CPF(11 位数字含校验位)或 CNPJ (14 位,数字或字母数字,含官方校验位,例如 00.000.000/E08G-12);墨西哥 RFC (12 或 13 位,日期段月份 01–12、日期 01–31)。格式错误返回 INVALID_REQUEST。 required 档未提交亦返回 INVALID_REQUEST。 · 最长 50 |
beneficiary.email |
string<email> | 可选 | 最长 200 |
beneficiary.phone |
string | 可选 | 最长 50 |
beneficiary.account |
string | 可选 | 最长 200 |
beneficiary.bank_code |
string | 可选 | 最长 20 |
beneficiary.branch_code |
string | 可选 | 最长 20 |
actual_beneficiary |
object | 可选 | The beneficiary the provider reported back after settling the transfer. Absent until a callback carries one, and absent for good on providers that do not report it. Compare it against beneficiary to tell whether the money reached the requested account. |
actual_beneficiary.name |
string | 可选 | 最长 200 |
actual_beneficiary.tax_id |
string | 可选 | 收款人证件号。账户 transfer_beneficiary_validation_mode 为 optional 或 required 且提交了本字段时,须符合账户市场格式:巴西 CPF(11 位数字含校验位)或 CNPJ (14 位,数字或字母数字,含官方校验位,例如 00.000.000/E08G-12);墨西哥 RFC (12 或 13 位,日期段月份 01–12、日期 01–31)。格式错误返回 INVALID_REQUEST。 required 档未提交亦返回 INVALID_REQUEST。 · 最长 50 |
actual_beneficiary.email |
string<email> | 可选 | 最长 200 |
actual_beneficiary.phone |
string | 可选 | 最长 50 |
actual_beneficiary.account |
string | 可选 | 最长 200 |
actual_beneficiary.bank_code |
string | 可选 | 最长 20 |
actual_beneficiary.branch_code |
string | 可选 | 最长 20 |
failure_reason |
string | 可选 | — |
failure_code |
string | 可选 | — |
created_at |
string<date-time> | 必填 | — |
updated_at |
string<date-time> | 必填 | — |
submitted_at |
string<date-time> | 可选 | — |
completed_at |
string<date-time> | 可选 | — |
failed_at |
string<date-time> | 可选 | — |
returned_at |
string<date-time> | 可选 | — |
authorization_url |
string<uri> | 可选 | Short-lived payer authorization URL, available after asynchronous channel submission. |
authorization_url_expires_at |
string<date-time> | 可选 | — |
metadata |
object | 可选 | — |
{ "id": "00000000-0000-7000-8000-000000000000", "transfer_number": "string", "payment_method": "string", "classification": { "classification_status": "resolved", "payment_category": "string", "payment_method": "string", "rail_variant": "string" }, "amount": 0, "currency": "string", "transferred_amount": 0, "returned_amount": 0, "status": "pending", "state": "string", "description": "string", "merchant_order_id": "string", "provider_transaction_id": "string", "beneficiary": { "name": "string", "tax_id": "string", "phone": "string", "account": "string", "bank_code": "string", "branch_code": "string" }, "actual_beneficiary": { "name": "string", "tax_id": "string", "phone": "string", "account": "string", "bank_code": "string", "branch_code": "string" }, "failure_reason": "string", "failure_code": "string", "created_at": "2026-01-01T00:00:00Z", "updated_at": "2026-01-01T00:00:00Z", "submitted_at": "2026-01-01T00:00:00Z", "completed_at": "2026-01-01T00:00:00Z", "failed_at": "2026-01-01T00:00:00Z", "returned_at": "2026-01-01T00:00:00Z", "authorization_url": "https://example.com", "authorization_url_expires_at": "2026-01-01T00:00:00Z", "metadata": {}}The request body or path parameters are invalid.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}The credential kind or host does not match the transfer service.
The account secret lacks the required transfer scope.
ACCOUNT_FEE_NOT_FOUND. No canonical transfer pricing policy matches this account, rail, currency and operation. The transfer is not created.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}The idempotency key or transfer state conflicts with the request.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}Credential lookup failed (INTERNAL_ERROR). The request handler was not executed.
Cancel a transfer intent
Section titled “Cancel a transfer intent”Send the idempotency key in X-Idempotency-Key or Idempotency-Key;
at least one is required. When both are sent they must be equal,
otherwise the request is rejected with 400 INVALID_REQUEST. The Ed25519
signature covers X-Idempotency-Key when it is sent, otherwise
Idempotency-Key.
路径参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
intent_id |
string | 必填 | — |
请求头
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
X-API-Key |
string | 必填 | — |
X-Timestamp |
string | 必填 | — |
X-Signature |
string | 必填 | — |
X-Idempotency-Key |
string | 可选 | Idempotency key. Send it in this header or in Idempotency-Key; at least one of the two is required. When this header is sent, the Ed25519 signature covers its value. If both headers are sent they must be equal, otherwise the request is rejected with 400 INVALID_REQUEST. · 最短 1 |
Idempotency-Key |
string | 可选 | Idempotency key, alternative to X-Idempotency-Key; at least one of the two is required. The Ed25519 signature covers this header only when X-Idempotency-Key is not sent. If both headers are sent they must be equal, otherwise the request is rejected with 400 INVALID_REQUEST. · 最短 1 |
请求体 application/json
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
reason |
string | 可选 | 最长 500 |
请求示例
curl -X POST 'https://transfer-api.psp.example.com/api/v1/payments/transfers/{intent_id}/cancel' \ -H 'X-API-Key: <api-key>' \ -H 'X-Timestamp: <timestamp>' \ -H 'X-Signature: <signature>' \ -H 'X-API-ID: <api-id>' \ -H 'Content-Type: application/json' \ -d '{ "reason": "string" }'响应
Transfer intent canceled
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
status |
enum | 必填 | 可选值:canceled |
{ "status": "canceled"}The request body or path parameters are invalid.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}The credential kind or host does not match the transfer service.
The account secret lacks the required transfer scope.
The transfer does not exist for this account.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}The idempotency key or transfer state conflicts with the request.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}Credential lookup failed (INTERNAL_ERROR). The request handler was not executed.
Request a transfer order sync
Section titled “Request a transfer order sync”Requires a transfer account secret and transfers:write scope. A
non-terminal transfer is never advanced by this request: the gateway
delivers one workflow command derived from the idempotency key and
returns action=update_transfer_workflow with synced=false once the
Transfer workflow accepts it. The workflow observes the provider and
alone decides the terminal state and funds; read the outcome from
webhooks or the query service. Retrying with the same idempotency key
maps to the same workflow command. A transfer that is not yet submitted
or whose submission is unconfirmed (state submission_unknown, even when
a provider ID was saved) returns action=none. A completed
transfer only refreshes its channel fee (action=query_channel_status).
If the transfer’s workflow run has failed, the request answers 503
until operations recover the workflow; merchant retries, with the same
or a new idempotency key, never restart it.
Send the idempotency key in X-Idempotency-Key or Idempotency-Key;
at least one is required. When both are sent they must be equal,
otherwise the request is rejected with 400 INVALID_REQUEST. The Ed25519
signature covers X-Idempotency-Key when it is sent, otherwise
Idempotency-Key.
路径参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
order_id |
string<uuid> | 必填 | — |
请求头
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
X-API-Key |
string | 必填 | — |
X-Timestamp |
string | 必填 | — |
X-Signature |
string | 必填 | — |
X-Idempotency-Key |
string | 可选 | Idempotency key. Send it in this header or in Idempotency-Key; at least one of the two is required. When this header is sent, the Ed25519 signature covers its value. If both headers are sent they must be equal, otherwise the request is rejected with 400 INVALID_REQUEST. · 最短 1 |
Idempotency-Key |
string | 可选 | Idempotency key, alternative to X-Idempotency-Key; at least one of the two is required. The Ed25519 signature covers this header only when X-Idempotency-Key is not sent. If both headers are sent they must be equal, otherwise the request is rejected with 400 INVALID_REQUEST. · 最短 1 |
请求示例
curl -X POST 'https://transfer-api.psp.example.com/api/v1/orders/{order_id}/sync' \ -H 'X-API-Key: <api-key>' \ -H 'X-Timestamp: <timestamp>' \ -H 'X-Signature: <signature>' \ -H 'X-API-ID: <api-id>'响应
Sync request handled; see action for what was done.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
order_id |
string<uuid> | 必填 | — |
order_type |
enum | 必填 | 可选值:transfer_intent、transfer_refund |
action |
enum | 可选 | update_transfer_workflow means the Transfer workflow accepted the sync command; the gateway did not query the provider or write state. · 可选值:none、query_channel_status、update_transfer_workflow |
previous_state |
string | 必填 | — |
current_state |
string | 必填 | Local state when the response was built; workflow results arrive asynchronously. |
synced |
boolean | 必填 | Always false for update_transfer_workflow. |
synced_at |
string<date-time> | 必填 | — |
message |
string | 可选 | — |
{ "order_id": "00000000-0000-7000-8000-000000000000", "order_type": "transfer_intent", "action": "none", "previous_state": "string", "current_state": "string", "synced": false, "synced_at": "2026-01-01T00:00:00Z", "message": "string"}The request body or path parameters are invalid.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}The credential kind or host does not match the transfer service.
The account secret lacks the required transfer scope.
The transfer does not exist for this account.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}Credential lookup failed (INTERNAL_ERROR). The request handler was not executed.
The Transfer workflow or provider cannot accept the request now; retry with the same idempotency key.
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 必填 | — |
message |
string | 必填 | — |
{ "code": "string", "message": "string"}