Pix on File Payment
Pix on File (JSR) payments require an active enrollment to be initiated.
- Merchant initiates payment referencing the enrollment
- System returns a FIDO2 challenge
- Customer authenticates using their registered FIDO2 credentials
- Payment is authorized and funds are transferred
Requirements
- EBANX Account
- API Credentials - Ensure you have your EBANX integration Key. If not, complete the Merchant Signup Form.
Pix on File is processed by the EBANX Brazilian payment institution, so all requests must be sent to the local hosts below — not to the cross-border hosts used by other payment methods.
- Sandbox:
https://sandbox-local-latam.ebanx.com - Production:
https://api-local-latam.ebanx.com
Payment Initiation
Pix on File Payments are initiated using the merchant_enrollment_code created during Device Linking.
| Parameter | Requirement | Description |
|---|---|---|
integration_key | Required | Your integration key |
type | Required | Must be request |
mode | Required | Must be full |
payment.country | Required | Must be br |
payment.currency_code | Required | Currency code |
payment.amount_total | Required | Total payment amount |
payment.merchant_payment_code | Required | Payment code |
payment.order_number | Optional | Order number |
payment.payment_type_code | Required | Must be pix-jsr |
payment.name | Required | Customer name |
payment.email | Required | Customer email |
payment.document | Required | Customer document |
payment.metadata.merchant_enrollment_code | Required | Unique enrollment code |
Sample Request
curl -X POST \
--location 'https://sandbox-local-latam.ebanx.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}"
}
}
}'
A successful request will return 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.
{
"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_challenge | The challenge to sign with the customer's FIDO2 authenticator. Present whenever the challenge was successfully obtained — see the note below. |
pix-jsr.hosted_url_payment | Returned 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. |
If fido_challenge is absent, do not call the authentication endpoint. Query the payment by hash and check payment["pix-jsr"].fido_challenge again — 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
After collecting the results of the FIDO2/WebAuthn authentication performed by the customer, send a payment authentication request using the parameters below to complete the payment.
| Parameter | Requirement | Description |
|---|---|---|
integration_key | Required | Your integration key |
hash | Required | Payment hash |
risk_signals | Required | Refer to the Risk Signals section. |
authentication.credentialId | Required | Credential ID used for the signature, in Base64url format |
authentication.rawCredentialId | Required | The credential ID in ArrayBuffer format (Base64url encoded) |
authentication.credentialType | Required | Must be public-key |
authentication.response.clientDataJSON | Required | Client data in JSON, encoded in Base64url |
authentication.response.authenticatorData | Required | Authenticator data encoded in Base64url |
authentication.response.signature | Required | Cryptographic signature of the data (the heart of authentication) |
authentication.response.userHandle | Required | The opaque user identifier, encoded in Base64URL (bytes) |
Sample Request
curl -X POST \
--location 'https://sandbox-local-latam.ebanx.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}"
}
}
}'
A successful request will return a JSON response like the one below. status: "SUCCESS" means the assertion was accepted — the payment itself remains pending at this point.
{
"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-jsr node is still present here: the payment remains PE after 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.
This 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 SUCCESS with accepted means 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 the SUCCESS above as a confirmed payment will fulfill orders that can still fail.
The payment reaches one of the following statuses after this call:
| Status | Meaning |
|---|---|
PE | Pending. Authentication accepted, awaiting confirmation. This is the expected immediate state. |
CO | Confirmed. This is the only status that authorizes order fulfillment. |
CA | Cancelled. The payment failed or was rejected and will not complete. |