Skip to main content
Unlisted page
This page is unlisted. Search engines will not index it, and only users having a direct link can access it.

Pix on File Payment

Pix on File (JSR) payments require an active enrollment to be initiated.

  1. Merchant initiates payment referencing the enrollment
  2. System returns a FIDO2 challenge
  3. Customer authenticates using their registered FIDO2 credentials
  4. 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.
Endpoint host

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.

Payment Initiation

Pix on File Payments are initiated using the merchant_enrollment_code created during Device Linking.

ParameterRequirementDescription
integration_keyRequiredYour integration key
typeRequiredMust be request
modeRequiredMust be full
payment.countryRequiredMust be br
payment.currency_codeRequiredCurrency code
payment.amount_totalRequiredTotal payment amount
payment.merchant_payment_codeRequiredPayment code
payment.order_numberOptionalOrder number
payment.payment_type_codeRequiredMust be pix-jsr
payment.nameRequiredCustomer name
payment.emailRequiredCustomer email
payment.documentRequiredCustomer document
payment.metadata.merchant_enrollment_codeRequiredUnique 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"
}
FieldDescription
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_challenge

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.

ParameterRequirementDescription
integration_keyRequiredYour integration key
hashRequiredPayment hash
risk_signalsRequiredRefer to the Risk Signals section.
authentication.credentialIdRequiredCredential ID used for the signature, in Base64url format
authentication.rawCredentialIdRequiredThe credential ID in ArrayBuffer format (Base64url encoded)
authentication.credentialTypeRequiredMust be public-key
authentication.response.clientDataJSONRequiredClient data in JSON, encoded in Base64url
authentication.response.authenticatorDataRequiredAuthenticator data encoded in Base64url
authentication.response.signatureRequiredCryptographic signature of the data (the heart of authentication)
authentication.response.userHandleRequiredThe 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.

Do not fulfill the order on this response

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:

StatusMeaning
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.