Withdrawal
On this page
A withdrawal sends money from your Payout balance to a bank account. Withdrawals go through the M2M Withdrawals API (API v2): a separate mTLS host, your QWAC certificate for the connection and a QSEAL signature on every request that creates or cancels a withdrawal.
-
Get and import your certificates
- Obtain a QWAC and a QSEAL certificate from a supported Qualified Trust Service Provider (currently I.CA and Disig).
- Import both via
POST /api/v1/mtls/certificatesand wait until Payout approves them. The whole process is described in Certificates.
-
Generate api key and secret
- You can do it in backoffice (Sandbox or Production) after you have already created account.
- It's required to add notify url before api key is generated. This url will be used for sending webhook notifications (POST HTTP Requests) about state of checkouts and other events.
-
Make authorization call to get Bearer token. This call goes to the standard host, not the mTLS one.
Command Linecurl --location --request POST 'https://sandbox.payout.one/api/v1/authorize' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --data-raw '{ "client_id": "DC995618-7ED8-4070-9DA0-48B6F86551C3", "client_secret": "q3dpHpYtDrH-KmGD4HMn5OTEx6IsZPBokQ8CqMONWqMSEePWy9bXd3Ua3KvO7f6C" }'Response of this call looks like this:
JSON{ "token": "SFMyNTY.g2gDYSFuBgCaSXELfgFiAAFRgWnBcvEfet1jIr9OPF984RGTKu-8HcHPQKJitk_kJKiU", "valid_for": 6000 } -
Prepare the withdrawal and sign it with your QSEAL certificate
Command LineBODY='{ "amount": 300, "currency": "EUR", "external_id": "PAYOUT-2026-0001", "iban": "SK3112000000198742637541", "customer": { "first_name": "John", "last_name": "Doe", "email": "john.doe@payout.one" }, "statement_descriptor": "Simple statement description" }' DIGEST="SHA-256=$(printf %s "$BODY" | openssl dgst -sha256 -binary | base64)" JWS_SIGNATURE="<detached JWS over $DIGEST, made with your QSEAL key>"Note
Amount is in cents (EUR), so 3 EUR is 300. It's same for other currencies, for example 300 CZK is 30000.
Digestis the SHA-256 of the exact body you send.X-JWS-Signatureis a detached JWS over theDigestvalue, made with the private key of your QSEAL certificate. Its protected header carries the thumbprint of the QSEAL certificate (x5t#S256) and the signing time (sigT), which must be within 5 minutes of the server time. The full header and a signing example are in M2M Withdrawals.Note
API v1 required a
signatureand anoncein the body. With QSEAL they are no longer needed: the signature covers the whole body. -
Create the withdrawal on the mTLS host. The connection presents your QWAC, the call carries the Bearer token from step 3 and the QSEAL headers from step 4.
Command Linecurl --location --request POST 'https://api-mtls-sandbox.payout.one/api/v2/withdrawals' \ --cert qwac.pem --key qwac.key \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer SFMyNTY.g2gDYSFuBgCaSXELfgFiAAFRgA.WnBcvEfet2jJr4OPF984RGTKu-8HcHPQKJitk_kJKiU' \ --header 'Accept: application/json' \ --header 'Idempotency-Key: 74775d02-745f-4198-cf3c-be9f1971dabe' \ --header "Digest: $DIGEST" \ --header "X-JWS-Signature: $JWS_SIGNATURE" \ --data "$BODY"Successful call returns
201 Createdwith the withdrawal:JSON{ "id": 52331, "object": "withdrawal", "amount": 300, "api_key_id": 42, "currency": "EUR", "external_id": "PAYOUT-2026-0001", "iban": "SK3112000000198742637541", "idempotency_key": "74775d02-745f-4198-cf3c-be9f1971dabe", "status": "pending", "metadata": {}, "statement_descriptor": "Simple statement description", "created_at": 1759744800, "nonce": "ZUc0Mk9sVXZDOXNsdklzMQ", "customer": { "first_name": "John", "last_name": "Doe", "name": "John Doe", "email": "john.doe@payout.one", "phone": null }, "signature": "0a6b7c2d9e1f4a3b5c8d7e6f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b" }Sending the same
Idempotency-Keyagain returns the existing withdrawal instead of creating a new one. -
Check the status of the withdrawal. Reading needs the QWAC and the Bearer token, but no QSEAL signature.
Command Linecurl --location --request GET 'https://api-mtls-sandbox.payout.one/api/v2/withdrawals/52331' \ --cert qwac.pem --key qwac.key \ --header 'Authorization: Bearer SFMyNTY.g2gDYSFuBgCaSXELfgFiAAFRgA.WnBcvEfet2jJr4OPF984RGTKu-8HcHPQKJitk_kJKiU' \ --header 'Accept: application/json'Withdrawal statuses:
pending- created, not processed yetin_transit- being processedpaid- processedcanceled- cancelledfailed- failed
-
Cancel the withdrawal if needed. Only a withdrawal that is still
pendingand has not been picked up for processing can be cancelled. Cancel is signed with QSEAL like step 4; the request has no body, soDigestis the SHA-256 of an empty body. Check cancel allowed tells you beforehand whether it is still possible.Command LineDIGEST="SHA-256=$(printf %s "" | openssl dgst -sha256 -binary | base64)" JWS_SIGNATURE="<detached JWS over $DIGEST, made with your QSEAL key>" curl --location --request POST 'https://api-mtls-sandbox.payout.one/api/v2/withdrawals/52331/cancel' \ --cert qwac.pem --key qwac.key \ --header 'Authorization: Bearer SFMyNTY.g2gDYSFuBgCaSXELfgFiAAFRgA.WnBcvEfet2jJr4OPF984RGTKu-8HcHPQKJitk_kJKiU' \ --header 'Accept: application/json' \ --header "Digest: $DIGEST" \ --header "X-JWS-Signature: $JWS_SIGNATURE"
All parameters, responses and errors of these calls are in the API reference. For production use https://app.payout.one for the authorization call and https://api-mtls.payout.one for the withdrawal calls.
- Need help? Contact support.
- Questions? Contact sales.
- Service status? status.payout.one.
- LLM? Read llms.txt.