Payments Guide
This guide covers everything you need to know about creating and managing payments through the 123hub API. All payment operations use a single endpoint with method-based routing.Overview
The 123hub API provides three payment methods through a single endpoint:Endpoint
All requests are sent to a single endpoint:success field in the response body to determine the outcome.
Authentication
Every request requires the application ID and exact-body hash. The timestamp and nonce are optional and must be supplied together when used:
The hash is computed as:
requestBody is the raw JSON string of the request body, and secretKey is your merchant secret key.
Request Format
All requests follow the same envelope:Response Format
All responses follow a consistent envelope:Identifiers
Every payment uses three identifiers that appear in theidentifiers object:
Use
c_id as your primary reference for tracking payments. It is the key you
control and should map to your internal order or transaction ID.Creating a Deposit (payment.in)
Usepayment.in to create a deposit where a customer pays you.
1
Build the request body
Include the payment amount, currency, customer (payer) details, and your
unique
c_id.2
Compute the authentication hash
Compute
sha512(requestBody + secretKey) and set it in the X-Data-Hash
header.3
Send the request
POST to
/public/api/multihub/v1 and handle the response.4
Redirect the customer
If the response includes a
redirect.to URL, redirect the customer to
complete payment.Request
Deposit Request Fields
Forpayment.in, payer is required and must be included under params.payment.payer.
Response
For UPI payments (India), the response may include a
redirect object with
UPI deep-link URLs in the redirect.to field. For other payment methods,
redirect may not be present in the initial response.Full Deposit Response Examples
- INR (UPI)
- TRY (Havale)
- ARS (Bank transfer)
Creating a Withdrawal (payment.out)
Usepayment.out to send money to a recipient (payout).
Use
params.payment.identifiers.c_id as your own payout identifier and
idempotency key. The same c_id is returned in the create response,
payment.status, and payout webhooks under
data.result.payment.identifiers.c_id.Request
Region-Specific Withdrawal Examples
Thereceiver.bank object varies by region. Below are the key differences:
- India (INR)
- Mexico (MXN)
- Argentina (ARS)
- Turkey (TRY)
Withdrawal Request Fields
Turkey (TRY) withdrawals use
bank_transfer with IBAN format in
receiver.bank.account.id (e.g., TR330006100519786457841326). No ifsc or
code is required.Deposits use
payer, withdrawals use receiver. The payer object
describes who is sending the money (deposit), while the receiver object
describes who is receiving the money (withdrawal). Both contain contact
information and, for receiver, bank account details.Tracking Withdrawal Completion
The initialpayment.out response usually has status.status: "processing". Wait for a webhook or poll payment.status with your c_id or the returned h_id.
Payout lifecycle webhooks use the same payment envelope as deposits. Read the business identifier from
data.result.payment.identifiers.c_id; do not depend on provider-only callback fields such as order_id, transaction_id, session_token, or user_id.
Full Withdrawal Response Examples
- ARS Payout
- TRY Payout
Checking Payment Status (payment.status)
Usepayment.status to query the current state of a payment. You can look up a payment by either c_id (your reference) or h_id (system-assigned ID).
Query by c_id
Query by h_id
You can also look up a payment using the system-assignedh_id. When using h_id, the service_id field is not required:
Response
The response contains the full payment object with its current status:Re-sending Webhook (payment.notification)
Usepayment.notification to trigger a webhook re-delivery for a specific payment. The request format is identical to payment.status, and the response returns the full payment object:
Provide either
c_id or h_id. This method triggers a new webhook delivery
to your active webhook endpoints with the current payment state. Use it only
as a recovery action when your webhook handler missed or failed to process a
notification. For read-only checks or polling, use payment.status with
backoff instead. The method is limited to 10 requests per minute. Without
operation_id, compatibility idempotency is scoped to the canonical request
and current minute.Payment Statuses
Each payment has a status object with the current status name, and boolean flags indicating whether it is final and whether it represents a success.Terminal statuses are indicated by
final: true. A terminal status is the
current completed outcome for integration handling, but reconciliation,
refunds, or provider corrections can publish a later status update. Always
process webhooks idempotently by payment id and status timestamp.Status Object Structure
Every payment includes astatus object with the following fields:
history array contains every status transition the payment has gone through, in chronological order. This is useful for debugging and auditing.
Handling Status Changes
Redirect URLs
For deposit payments (payment.in), the response may include a redirect object. For UPI payments (India), this contains deep-link URLs for mobile payment apps:
The
redirect.to field can contain UPI deep-link URLs, a provider HTTPS
payment page URL, or another provider-specific redirect target. The redirect
field may be absent if no redirect URL is available for the payment method.Deposit Response by Region
For bank transfer deposits, the response may include payment details the customer needs to complete the transfer. The exact fields depend on the region:
For TRY and ARS, the
receiver.bank_account object contains the bank details the customer must transfer to:
Pago Móvil and similar P2P routes may return additional typed instructions:
bankDetails.* targets.
Customer Data
Deposits: the payer Object
For payment.in requests, the payer object describes the customer making the payment:
Withdrawals: the receiver Object
For payment.out requests, the receiver object describes who receives the payout, including their bank details:
receiver.bank object contains the banking details required to execute the transfer. The specific fields depend on the region and payment method:
Additional Response Fields
Operations
Every payment response includes anoperations array and an operation shortcut:
Identifier Formats
Theh_id format varies by provider. Treat it as an opaque string:
- Some providers return numeric strings (e.g.,
"1774892151645") - Others return UUIDs (e.g.,
"b8adedc9-c245-4fa2-8f26-095e8117d11a")
status.error Field
The status.error field inside the payment status object can be:
null— no errorinteger— error code (e.g.,7001)string— error message from provider (e.g.,"Sum 150000 is lower than 200000")
Do not confuse
result.payment.status.error (integer/string/null inside the
payment status) with the top-level error object in error API responses
(which has code, message, details, context fields).Bank Details in payment.status
Idempotency
Thec_id (Client ID) serves as your idempotency key. If you send a payment.in or payment.out request with a c_id that was already used, the API will return error code 6009 (Payment already exists) instead of creating a duplicate.
Error Handling
When a request fails, the response will havesuccess: false and include an error object. Error responses return HTTP 400:
Successful responses return HTTP 200. Error responses return HTTP 400 (or HTTP
404 for unknown methods). Always check the
success field in the response
body to determine the outcome.Error Codes
Error Handling Example
Best Practices
Use Unique c_id Values
Always assign a unique
c_id to each payment. This serves as your
idempotency key and prevents duplicate payments.Compute Hashes Server-Side
Never expose your secret key to the client. Always compute the
X-Data-Hash
on your server.Check success Field
Always check the
success boolean in the response body to determine the
outcome. Success returns HTTP 200, errors return HTTP 400.Store All Identifiers
Save
c_id, h_id, and p_id from the response for reconciliation,
debugging, and support inquiries.Handle Redirects
For deposits, always check for a
redirect.to URL and redirect the customer
to complete their payment.Use Status History
The
status.history array provides a complete audit trail. Use it for
debugging and tracking payment lifecycle.