Cross-border Transfer Overview
Follow a transfer from sender registration and customer confirmation to collection and the final CNY payout.
Use cross-border transfers to collect a customer's payment in a supported source currency and pay their beneficiary in CNY. Your application registers the sender, creates the transfer request, shows the quote, and initiates collection. After collection succeeds, HoneyCoin reviews and processes the beneficiary payout. Your application tracks the result and informs the customer when the transfer is complete.
There are two separate payment stages: collecting the source funds and paying the beneficiary. A successful collection means the transfer is funded. The transfer is delivered only when the request reaches payout_successful.
Transfer flow at a glance
This diagram follows the eight steps below. It shows the production flow; sandbox simulates collection and payout. All API paths are relative to the cross-border requests base URL.
flowchart TD
A["1. Register or reuse the sender<br/>POST /senders → save senderId"]
B["2. Collect transfer and beneficiary details<br/>Amount, purpose, recipient identity<br/>and beneficiary.payoutDetails"]
C["3. Create the request and get a quote<br/>POST / → save requestId<br/>pending_charge · No money collected"]
D["4. Show the quote and recipient details<br/>Customer confirms in your application"]
E["5. Initiate collection<br/>POST /charges/{requestId} · No body<br/>Save transactionId · charge_initiated"]
F["6. Confirm collection success<br/>Track transaction_updated or GET /transactions/{transactionId}<br/>charge_successful · Transfer funded"]
G["7. HoneyCoin reviews and processes the CNY payout<br/>Track crossborder_updated or GET /{requestId}<br/>payout_initiated · Keep tracking while pending"]
H["8. Confirm delivery and notify the customer<br/>payout_successful · Beneficiary paid"]
X["Close the unpaid request if eligible<br/>POST /{requestId}/close · No body<br/>No pending or successful deposit; no payout<br/>Closing does not refund funds"]
Y["Reconcile the request and its deposits<br/>Retry only when the request is eligible<br/>and no pending or successful deposit exists"]
Z["Contact support with request and transaction IDs<br/>Do not collect the source payment again"]
A --> B --> C --> D
D -->|Confirmed| E
D -.->|Customer cancels| X
E -->|Collection succeeds| F
E -.->|charge_failed| Y
Y -.->|Eligible retry: same requestId| E
F --> G
G -->|Payout succeeds| H
G -.->|payout_failed| Z
classDef prepare fill:#F8FAFC,stroke:#CBD5E1,color:#172033
classDef collect fill:#EFF6FF,stroke:#60A5FA,color:#172033
classDef payout fill:#F5F3FF,stroke:#A78BFA,color:#172033
classDef complete fill:#ECFDF5,stroke:#34D399,color:#064E3B
classDef recovery fill:#FFFBEB,stroke:#FBBF24,color:#78350F
class A,B,C,D prepare
class E,F collect
class G payout
class H complete
class X,Y,Z recovery
While a collection or payout is pending, keep tracking it. Reconcile timeouts before retrying. For exact eligibility rules and refund states, see Status, Webhooks and Retries.
Before you start
Obtain a bearer token and configure webhooks for your environment. Keep your API calls on your server.
The endpoints below are relative to this production base URL:
https://api-v2.honeycoin.app/api/b2b/cross-border/requestsFor sandbox, use /api/sandbox/b2b/cross-border/requests on the same host, with sandbox credentials and sender records. Follow Testing Cross-border Transfers for test values and environment differences.
1. Register the person or business sending the money
Collect the sender's identity, contact and address details. Individuals provide idNumber; businesses provide registrationNumber. Both provide idType and idCountry. Create an individual or business sender with Create a Cross-border Sender:
POST /senders
Save the returned data.id as senderId. You can reuse an active sender for future transfers from the same person or business. If you already have their sender ID in this environment, use that record instead of registering them again.
The sender is the person or business funding the transfer. You will supply the beneficiary's account separately in the next step. Alipay payouts require an individual sender.
2. Collect the transfer and beneficiary details
Ask the customer how much they want to send, why they are sending it, and who should receive it. Prepare:
| Information | What to supply |
|---|---|
| Sender | The saved senderId |
| Source payment | A positive amount in chargeCurrency, plus the payer's chargeDetails |
| Purpose | purpose, and subPurpose when required for goods or services |
| Beneficiary | Recipient identity in beneficiary, with CNY bank or Alipay account details in beneficiary.payoutDetails |
| Your reference | A unique externalReference for this transfer request |
Use requestType: transfer and receiverCurrency: CNY. Source currencies are KES or NGN, subject to collection availability for your account. New production requests use mobile money (chargeDetails.method: momo). Select a country, currency and operator combination available for your account.
Set beneficiary.type to describe the recipient. Include idType and idCountry, plus idNumber for an individual or registrationNumber for a business. Do not send both number fields. The beneficiary's identity belongs to the recipient; it is separate from the saved sender identity.
For a bank beneficiary, select the bank from the China bank directory and include its code. For Alipay, supply the recipient's Alipay account identifier and account holder name. Place these payment instructions inside beneficiary.payoutDetails, and include the full beneficiary object when creating the request. See the transfer guide for full request examples and purpose values.
3. Create the transfer request and obtain its quote
Send those details to Create a Cross-border Request:
POST /
Save data.id as the request ID, alongside your externalReference. The response includes a quote and the saved beneficiary, and the request starts at pending_charge.
At this point, you have created the transfer instructions and obtained the quoted amounts. The customer has not been charged.
4. Show the quote and ask the customer to confirm
Show the customer the source amount and currency from quote.senderAmount and quote.senderCurrency, the beneficiary amount and currency from quote.receiverAmount and quote.receiverCurrency, and the recipient details.
Use the returned amounts directly. The amount you submitted is the source amount; it is not the CNY amount the beneficiary receives. quote.expiresAt is currently null, so do not display an invented quote-expiry countdown.
Customer confirmation happens in your application. Once they confirm, proceed to the charge call. If they abandon the transfer, you can close the unpaid request while it is eligible.
5. Initiate the source payment
Call Initiate a Cross-border Charge using the saved request ID:
POST /charges/{requestId}
Send no body. HoneyCoin uses the quote amount and collection details already saved on the request.
Save the returned data.transactionId as the charge transaction ID, linked to the request ID. The customer completes the mobile money payment using the applicable payment prompts. Track charge_initiated as collection in progress; a successful initiation response does not establish that the customer paid.
6. Confirm that the source payment succeeded
Track the charge through transaction_created and transaction_updated webhooks. These events identify the charge using data.transactionId. You can also fetch the charge transaction:
GET /transactions/{transactionId}
A transaction with type: crossborder-deposit and chargeStatus: successful confirms collection. The cross-border request progresses to charge_successful.
Your customer-facing message can now say that the payment was received and the beneficiary payout is being processed. Keep the transfer open: the beneficiary has not yet been confirmed as paid.
7. Wait for HoneyCoin to process the CNY payout
After successful collection, HoneyCoin reviews the transfer and processes the payout to the saved beneficiary. Your application does not call a customer payout-initiation endpoint for this stage.
Track the request through crossborder_updated, which identifies the request using data.id, or fetch the request:
GET /{requestId}
payout_initiated means the beneficiary payment is being processed. Continue to show the transfer as in progress.
8. Confirm completion and notify the customer
When the request reaches payout_successful, mark the beneficiary transfer as completed and notify the customer. Retain the request ID, your external reference and the related transaction IDs for reconciliation and support.
If an event arrives late or conflicts with a status you already recorded, fetch the request to reconcile its current state. Process repeated webhook deliveries without repeating the customer-facing or financial effect.
Keep these three IDs separate
| ID | Represents | Used for |
|---|---|---|
senderId | The person or business sending money | Creating transfer requests |
| Request ID | The overall cross-border transfer | Initiating its charge, tracking the CNY payout, and closing an eligible unpaid request |
| Charge transaction ID | One attempt to collect the source payment | Tracking the collection result |
The local payment webhook uses data.transactionId. The cross-border lifecycle webhook uses data.id. A successful charge alone must not mark the overall request as delivered.
If the transfer does not complete as expected
| Situation | What to do |
|---|---|
| Create or charge call times out | Fetch the saved request and list its transactions before submitting another payment attempt. If you did not receive the request ID, list requests and match your external reference |
| Collection fails | Reconcile the request and deposits. Retry the saved charge only when the request is eligible and no pending or successful deposit exists |
| Beneficiary payout fails | Contact support with the request ID and related transaction IDs. Do not collect the source payment again |
| Customer cancels before payment | Close the unpaid request if eligible. Closing cannot cancel an active payment or refund collected funds |
Continue with the sender guide, transfer request examples, and status, webhook and retry rules for implementation details.
Updated about 15 hours ago
