Pix on File Payment
Pix on File is a Pix payment flow in Brazil that allows customers to authorize payments with a device linked to their bank account, without being redirected to their bank app for each purchase. Pix on File is available on both the Cross-border and Local tenants.
Every payment references an active enrollment created during Device Linking, and the customer confirms it with the FIDO2/WebAuthn credential registered on their device.
This guide outlines the key concepts and implementation details required to accept Pix on File payments via API. It covers essential steps such as creating the payment request, authenticating it with the customer's FIDO2 credential, and monitoring the payment until it is confirmed.
Requirements
- API authentication - All API requests must be authenticated using JWS (JSON Web Signature). The legacy
integration_keyis being deprecated — if you still use it, follow the Migration Guide to transition to JWS. If you don't have credentials yet, complete the Merchant Signup Form. - Familiarity with EBANX Direct - This setup follows the same general structure as other payment methods, with a few unique parameters. See EBANX Direct for more info.
- Active enrollment - The customer must have an
acceptedenrollment. See Device Linking.
How it works
- Initiate payment - The merchant creates a payment referencing the customer's enrollment.
- FIDO2 challenge - EBANX returns a FIDO2 challenge in the response.
- Customer authentication - The customer signs the challenge with their registered FIDO2 credential, and the merchant sends the result to EBANX.
- Payment confirmation - EBANX updates the payment status from pending (PE) to confirmed (CO) once the payment is completed. If the payment fails, the status updates to cancelled (CA).
Instructions
Follow the steps below.
The sample requests on this page are sent to the Local sandbox host. If you operate Cross-border, send the same request to the Cross-border host — paths and payloads are identical.
- Select your environment
Select the appropriate environment for your integration. Use the sandbox environment for testing, or the production environment for live transactions. Use the URL for your HTTP requests based on your selection.
Check the method's availability for your country and tenant in Payment Methods by Country. Questions about tenant and environment? Check our API Operability and API Endpoints.
Cross-border sandboxhttps://sandbox.ebanxpay.com/ws/direct - Payment request
Pix on File payments are initiated with the ws/direct endpoint, using the
merchant_enrollment_codecreated during Device Linking.Parameter Requirement Description integration_keyRequired Your integration key typeRequired Must be requestmodeRequired Must be fullpayment.countryRequired Must be brpayment.currency_codeRequired Currency code payment.amount_totalRequired Total payment amount payment.merchant_payment_codeRequired Payment code payment.order_numberOptional Order number payment.payment_type_codeRequired Must be pix-jsrpayment.nameRequired Customer name payment.emailRequired Customer email payment.documentRequired Customer document payment.metadata.merchant_enrollment_codeRequired Unique enrollment code Sample request
Shellcurl -X POST \
--location 'https://sandbox-local-latam.ebanxpay.com/ws/direct' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"type": "request",
"mode": "full",
"payment": {
"country": "br",
"currency_code": "BRL",
"amount_total": "{total_amount}",
"merchant_payment_code": "{merchant_payment_code}",
"order_number": "{order_number}",
"payment_type_code": "pix-jsr",
"name": "John Doe",
"email": "john.doe@example.com",
"document": "{{tax_id}}",
"metadata": {
"merchant_enrollment_code": "{merchant_enrollment_code}"
}
}
}' - Payment response
A successful request returns a JSON response like the one below, creating a payment request in pending status and providing the cryptographic challenge (Base64url) that must be signed by the client's FIDO2 authenticator to complete the payment.
JSON{
"payment": {
"hash": "{payment_hash}",
"country": "br",
"merchant_payment_code": "{merchant_payment_code}",
"order_number": "{order_number}",
"status": "PE",
"open_date": "{open_date}",
"amount_br": "{amount_br}",
"amount_ext": "{amount_ext}",
"amount_iof": "{amount_iof}",
"currency_rate": "{currency_rate}",
"currency_ext": "BRL",
"due_date": "{due_date}",
"payment_type_code": "pix-jsr",
"pix-jsr": {
"fido_challenge": "{fido_challenge}",
"hosted_url_payment": "{hosted_url_payment}"
}
},
"status": "SUCCESS"
}Field Description pix-jsr.fido_challengeThe challenge to sign with the customer's FIDO2 authenticator. Present whenever the challenge was successfully obtained — see the note below. pix-jsr.hosted_url_paymentReturned for Pix JSR payment responses while the payment status is PE. EBANX-hosted page that runs the authentication ceremony for you. Ignore it on this flow; it is used by the Hosted Flow integration.Handle a missing fido_challengeIf
fido_challengeis absent, do not call the authentication endpoint. Query the payment by hash and checkpayment["pix-jsr"].fido_challengeagain — the query response is built the same way, so a challenge that has since been recorded will appear there. Do not create a replacement payment solely because this field is absent on the first response. - Payment authentication request
After collecting the results of the FIDO2/WebAuthn authentication performed by the customer, send a payment authentication request to the ws/payment/authentication endpoint using the parameters below to complete the payment.
Parameter Requirement Description integration_keyRequired Your integration key hashRequired Payment hash risk_signalsRequired Refer to Risk Signals. authentication.credentialIdRequired Credential ID used for the signature, in Base64url format authentication.rawCredentialIdRequired The credential ID in ArrayBuffer format (Base64url encoded) authentication.credentialTypeRequired Must be public-keyauthentication.response.clientDataJSONRequired Client data in JSON, encoded in Base64url authentication.response.authenticatorDataRequired Authenticator data encoded in Base64url authentication.response.signatureRequired Cryptographic signature of the data (the heart of authentication) authentication.response.userHandleRequired The opaque user identifier, encoded in Base64URL (bytes) Sample request
Shellcurl -X POST \
--location 'https://sandbox-local-latam.ebanxpay.com/ws/payment/authentication' \
--header 'Content-Type: application/json' \
--data '{
"integration_key": "{{integration_key}}",
"hash": "{payment_hash}",
"risk_signals": {},
"authentication": {
"credentialId": "{credential_id_base_64}",
"rawCredentialId": "{credential_id_array_buffer_base_64}",
"credentialType": "public-key",
"response": {
"clientDataJSON": "{client_data_json_in_base_64}",
"authenticatorData": "{authenticator_data_in_base_64}",
"signature": "{cryptographic_signature}",
"userHandle": "{user_handle}"
}
}
}' - Payment authentication response
A successful request returns a JSON response like the one below.
status: "SUCCESS"means the assertion was accepted — the payment itself remains pending at this point.JSON{
"payment": {
"hash": "{payment_hash}",
"country": "br",
"merchant_payment_code": "{merchant_payment_code}",
"order_number": "{order_number}",
"status": "PE",
"status_date": null,
"open_date": "{open_date}",
"confirm_date": null,
"amount_br": "{amount_br}",
"amount_ext": "{amount_ext}",
"amount_iof": "{amount_iof}",
"currency_rate": "1.0000",
"currency_ext": "BRL",
"due_date": "{due_date}",
"payment_type_code": "pix-jsr",
"pix-jsr": {
"fido_challenge": "{fido_challenge}",
"hosted_url_payment": "{hosted_url_payment}"
}
},
"status": "SUCCESS"
}The
pix-jsrnode is still present here: the payment remainsPEafter a successful authentication, and the challenge stays recorded, so both fields are returned again. Ignore them at this stage — the assertion has already been submitted.Do not fulfill the order on this responseThis call is synchronous but not conclusive. A successful authentication does not mean the payment is complete: the provider reports the payment completed, after which EBANX marks it
CO(confirmed), and that transition is delivered asynchronously through the payment status-change notification.This is the opposite of Device Linking confirmation, which is conclusive — there, a
SUCCESSwithacceptedmeans the enrollment is immediately usable. Do not reuse that assumption here.Release goods or services only when you receive
CO, either from the status-change notification or by querying the payment. Treating theSUCCESSabove as a confirmed payment will fulfill orders that can still fail.The payment reaches one of the following statuses after this call:
Status Meaning PEPending. Authentication accepted, awaiting confirmation. This is the expected immediate state. COConfirmed. This is the only status that authorizes order fulfillment. CACancelled. The payment failed or was rejected and will not complete. Notifications
-
EBANX will send a notification whenever a payment status changes.
-
Make sure your system is set up to receive notifications from EBANX for any changes in payment status.
Status
-
After receiving a notification, retrieve the payment status.
-
When a payment is confirmed, the status will change from pending (PE) to confirmed (CO). If the payment fails or is rejected, the status will update to cancelled (CA).
-
- Congratulations!
You have successfully integrated Pix on File payments.
For more information, refer to theDirect API reference guidechevron_right
Resources
Use the following resources when testing in your sandbox environment.
API Reference
Click here to access detailed API documentation to integrate efficiently.
Mock Customer Data
Click here to view mock customer data for testing and validating user flows.
Error Codes
Click here to review common error codes to troubleshoot and resolve issues quickly.
Still need help?
We hope this article was helpful. If you still have questions, you can explore the following options:
- Merchant support: Contact our support team at sales.engineering@ebanx.com for assistance.
- Not a partner yet? Please complete the Merchant Signup Form, and our commercial team will reach out to you.