Wallet payments

Wallet payments (WALLET) let users pay by authenticating with their wallet provider (the wallet app or service that confirms the payment).

⚠️

Do not start new integrations on the legacy wallet token model

If you are integrating for the first time, use the Enrollment API for all tokenized and recurring wallet flows. The legacy wallet.token model is supported for existing merchants only. It does not receive new feature development. Starting on the legacy model might require a migration later.

For tokenized/recurring flows, dLocal supports two integration models:

  • Enrollment API (use this for all new integrations): The user completes a one-time redirect to authorize future payments. dLocal returns an enrollment ID used for all subsequent direct charges. No redirect or re-authentication required.
  • Legacy wallet token (existing merchants only): The user completes a redirect and the webhook returns a wallet.token. No new integrations should use this model. See Tokenized wallets: Legacy.

Prerequisites

Complete these steps before you create a wallet payment:

  1. Use the Create payment endpoint for one-time wallet payments and legacy token enrollment. Use the Create enrollment endpoint for new Enrollment API integrations.
  2. Identify the wallet payment_method_id for the user's country in the Payment method section.
  3. Set payment_method_flow based on the payment flow:
    • Use REDIRECT for one-time payments and enrollment.
    • Use DIRECT only after you receive and store a valid wallet.token (legacy) or an ACTIVE enrollment ID (Enrollment API).
  4. Include notification_url to receive the final asynchronous payment or enrollment status.
  5. Include callback_url for REDIRECT flows so the wallet provider can return the user to your site.
  6. Include device.type for all REDIRECT requests.

Related references

Use these pages when you build and validate your integration:

  • Create payment: create one-time wallet payments, legacy token enrollments, and recurring DIRECT charges.
  • Create enrollment: create enrollments using the Enrollment API (recommended for new integrations).
  • Get enrollment: retrieve enrollment status. Use this to check the current state if you miss an enrollment webhook.
  • Cancel an enrollment: cancel an active enrollment when a user unsubscribes or changes their payment method.
  • The wallet object: review the supported wallet fields for the legacy flow, including save, verify, capture, and token.
  • Payment method section: confirm wallet availability, country support, and payment-method-specific requirements.
  • Receive notifications: implement webhook handling for asynchronous PENDING, PAID, REJECTED, VERIFIED, and ACTIVE updates.
  • Cancel a wallet.token: cancel a stored legacy token when a user cancels or changes their payment method.

Available wallets

To integrate wallet payments, identify each wallet you want to support and set its payment_method_id in the payment request.

📘

Payment method list

Get the payment method list or view all available wallets by country in the Payment method section.

Payment flow

Choose one of these flows based on whether you need a one-time payment or future DIRECT charges.

FlowDescriptionBest for
One-time payments (REDIRECT)Redirect the user to the wallet's website to authenticate and complete the payment. After authentication, the wallet provider redirects the user back to your site. dLocal does not issue a token.One-time purchases
Tokenized (recurring) payments: Enrollment API (REDIRECT, then DIRECT) 🆕Redirect the user once to authorize future payments via the Create enrollment endpoint. dLocal returns an enrollment ID. Use it for subsequent DIRECT payments without redirecting the user again.Subscriptions, recurring billing. Recommended for new integrations.
Tokenized (recurring) payments: Legacy (REDIRECT, then DIRECT) ❗Redirect the user to the wallet's website to authenticate and authorize future payments. Send wallet.save = true in the request. The asynchronous notification includes a wallet.token. Use that token for subsequent DIRECT payments. Do not use for new integrations. See Tokenized wallets: Legacy.Existing merchants only. No new integrations.

One-time payments

In this flow, redirect the user to the wallet's app/website to authenticate and complete the payment.

Sale

{
    "amount": 26,
    "currency": "BRL",
    "country": "BR",
    "payment_method_id": "PZ",
    "payment_method_flow": "REDIRECT",
    "payer": {
      "name": "Example Payer",
      "email": "[email protected]",
      "document": "<DOCUMENT_NUMBER>"
    },
    "device": {
      "type": "WEB"
    },
    "order_id": "5346523564",
    "notification_url": "http://merchantsite.com/notifications",
    "callback_url": "http://merchantsite.com/callback"
  }
{
  "id": "R-4-41f8628f-b6ec-4c02-96d5-c5b03cac7cb0",
  "amount": 26,
  "currency": "BRL",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "country": "BR",
  "created_date": "2018-12-26T20:37:20.000+0000",
  "status": "PENDING",
  "status_detail": "The payment is pending.",
  "status_code": "100",
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "redirect_url": "https://pay.dlocal.com/gmf-apm/payments-redirect/M-0aa0cc00-..."
}
{
  "id": "R-4-41f8628f-b6ec-4c02-96d5-c5b03cac7cb0",
  "amount": 26,
  "currency": "BRL",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "country": "BR",
  "created_date": "2018-12-26T20:37:20.000+0000",
  "status": "PAID",
  "status_detail": "The payment was paid.",
  "status_code": "200",
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications"
}

After you receive the synchronous response, redirect the user to redirect_url. dLocal sends the final PAID or REJECTED status by webhook to your notification_url.

Tokenized wallets: Enrollment API

👍

Recommended for new integrations

Use the Enrollment API to establish a reusable authorization. All subsequent charges go directly, with no redirect or re-authentication required. For method-specific parameters, see Yape Recurring and Pix with Biometrics.

The Enrollment API supports two integration patterns:

PatternWhen to use
Enrollment only (POST /enrollments)Establish the user authorization without an initial charge. Use when enrollment and first payment happen at different steps.
Payment + Enrollment in the same request (POST /payments with enrollment object)Create a payment and establish the authorization in a single API call. Use when the first charge and enrollment happen simultaneously.

Enrollment only

Use POST /enrollments when you want to create the enrollment without an initial payment. See the full Create enrollment API reference for all available fields.

Enrollment types:

The valid type values depend on the payment method. Not all payment methods support all types.

  • ON_DEMAND: Merchant initiates recurring payments at any time, with no frequency or amount restrictions. Valid for all enrollment-capable payment methods.
  • MERCHANT_SUBSCRIPTION: Merchant initiates recurring payments based on defined subscription settings (frequency, amount, dates). Only valid for payment methods that expose a structured subscription protocol (for example, Pix Automático). See the individual payment method pages to confirm which type applies.
ℹ️

external_id

external_id is your internal identifier for the enrollment. It appears in all enrollment webhooks, letting you correlate dLocal enrollment events back to your own records.

{
  "currency": "BRL",
  "country": "BR",
  "type": "ON_DEMAND",
  "payment_method_id": "<PM_CODE>",
  "payment_method_flow": "REDIRECT",
  "payer": {
    "name": "Example Payer",
    "document": "<DOCUMENT_NUMBER>",
    "email": "[email protected]"
  },
  "device": {
    "type": "WEB"
  },
  "external_id": "<YOUR_EXTERNAL_ID>",
  "description": "Subscription enrollment",
  "notification_url": "http://merchantsite.com/notifications",
  "callback_url": "http://merchantsite.com/callback"
}
{
  "id": "E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4",
  "external_id": "<YOUR_EXTERNAL_ID>",
  "currency": "BRL",
  "country": "BR",
  "type": "ON_DEMAND",
  "payment_method_id": "<PM_CODE>",
  "payment_method_flow": "REDIRECT",
  "created_date": "2025-12-26T20:37:20.000+0000",
  "status": "PENDING",
  "status_detail": "The enrollment is pending.",
  "status_code": "100",
  "redirect_url": "https://pay.dlocal.com/gmf-apm/payments/E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4",
  "notification_url": "http://merchantsite.com/notifications"
}
{
  "id": "E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4",
  "external_id": "<YOUR_EXTERNAL_ID>",
  "currency": "BRL",
  "country": "BR",
  "type": "ON_DEMAND",
  "payment_method_id": "<PM_CODE>",
  "payment_method_flow": "REDIRECT",
  "created_date": "2025-12-26T20:37:20.000+0000",
  "status": "ACTIVE",
  "status_detail": "The enrollment is active.",
  "status_code": "200",
  "notification_url": "http://merchantsite.com/notifications"
}

After receiving the synchronous response, redirect the user to redirect_url. The user completes authorization with their wallet provider. dLocal then sends the enrollment webhook to your notification_url with the final status.

ℹ️

callback_url behavior

When and how the user lands on callback_url after completing the enrollment redirect depends on the payment method. See the individual payment method pages for specifics.

📘

Enrollment ID

Once the enrollment status is ACTIVE, the id field (for example, E-4-32e1218f-...) is your enrollment ID. Persist it: it must be included in all subsequent recurring payment requests for this user.

To check the current enrollment status at any time (for example, if your server was temporarily unavailable), use the Get enrollment endpoint.

To cancel an enrollment, use the Cancel an enrollment endpoint.

Enrollment status codes:

For the full list of enrollment status_code values and their meanings, see the Get enrollment and Create enrollment API references.

statusstatus_codeDescription
PENDING100The enrollment has been created and is awaiting user authorization.
ACTIVE200The user completed authorization. The enrollment ID is ready to use for recurring charges.
CANCELLED400The enrollment was cancelled.
REJECTED300The user did not complete or declined the authorization.
ℹ️

Examples contain placeholders

Replace <PM_CODE> with the payment_method_id of the wallet you are integrating (for example, YE for Yape Recurring). See the Payment method section for all available IDs.

Payment + Enrollment in the same request

Include an enrollment object in a POST /payments call to create a payment and an enrollment in one request. Use this pattern when the first charge and enrollment happen simultaneously. See the Create payment and Create enrollment API references for all available fields.

ℹ️

Payment method-specific requirements

The example below uses payment_method_flow: "DIRECT" as a generic skeleton. For Yape (YE), the first enrollment+payment request must use payment_method_flow: "REDIRECT".

Yape requires a user redirect for first-time authorization. See the Yape Recurring section for the correct Yape-specific example.

Yape also requires device.type in all enrollment requests, and payer.phone is mandatory when device.type is WEB.

{
  "amount": 285,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "<PM_CODE>",
  "payment_method_flow": "DIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "device": {
    "type": "WEB"
  },
  "enrollment": {
    "external_id": "<YOUR_EXTERNAL_ID>",
    "type": "ON_DEMAND",
    "description": "Monthly subscription authorization",
    "notification_url": "https://merchantsite.com/enrollment_notifications",
    "callback_url": "https://merchantsite.com/enrollment_callback"
  },
  "order_id": "ord-221124442ab",
  "notification_url": "https://merchantsite.com/payments",
  "callback_url": "https://merchantsite.com/payment_callback"
}
{
  "id": "R-4-22112444-2ab0-4f5g-6h7i-8j9k0l1m2n3o",
  "amount": 285,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "<PM_CODE>",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "created_date": "2024-07-26T20:37:20.000+0000",
  "status": "PENDING",
  "status_detail": "The payment is pending.",
  "status_code": "100",
  "order_id": "ord-221124442ab",
  "notification_url": "https://merchantsite.com/payments",
  "redirect_url": "https://pay.dlocal.com/gmf-apm/payments-redirect/M-0aa0cc00-...",
  "enrollment": {
    "id": "E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4",
    "external_id": "<YOUR_EXTERNAL_ID>",
    "created_date": "2024-07-26T20:37:20.000+0000",
    "status": "PENDING",
    "status_detail": "The enrollment is pending.",
    "status_code": "100"
  }
}
{
  "id": "E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4",
  "external_id": "<YOUR_EXTERNAL_ID>",
  "currency": "BRL",
  "country": "BR",
  "type": "ON_DEMAND",
  "payment_method_id": "<PM_CODE>",
  "payment_method_flow": "REDIRECT",
  "created_date": "2024-07-26T20:37:20.000+0000",
  "status": "ACTIVE",
  "status_detail": "The enrollment is active.",
  "status_code": "200",
  "notification_url": "https://merchantsite.com/enrollment_notifications"
}
{
  "id": "R-4-22112444-2ab0-4f5g-6h7i-8j9k0l1m2n3o",
  "amount": 285,
  "status": "PAID",
  "status_detail": "The payment was paid.",
  "status_code": "200",
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "<PM_CODE>",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "enrollment": {
    "id": "E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4",
    "external_id": "<YOUR_EXTERNAL_ID>"
  },
  "order_id": "ord-221124442ab",
  "notification_url": "https://merchantsite.com/payments",
  "created_date": "2024-07-26T20:37:20.000+0000"
}
📘

Single request, dual outcome

This request produces two independent asynchronous notifications: one for the enrollment (sent to enrollment.notification_url) and one for the payment (sent to notification_url). They may arrive in any order. Persist the enrollment.id only after the enrollment notification reaches ACTIVE status. Grant entitlement only after the payment notification reaches PAID status.

Recurring charges with an enrollment ID

Once the enrollment is ACTIVE, charge the user directly. Add enrollment.id inside an enrollment object in subsequent POST /payments calls. No redirect or re-authentication required. See the Create payment API reference for the full list of fields.

{
  "amount": 26,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "<PM_CODE>",
  "payment_method_flow": "DIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "enrollment": {
    "id": "E-4-32e1218f-b6ec-3f21-13d5-50v12ere2ca4"
  },
  "order_id": "ord-221124442cd",
  "notification_url": "https://merchantsite.com/payments"
}
{
  "id": "R-4-55ab7891-cd12-4ef3-ab56-789012cdef34",
  "amount": 26,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "<PM_CODE>",
  "payment_method_type": "WALLET",
  "payment_method_flow": "DIRECT",
  "created_date": "2024-07-27T10:15:00.000+0000",
  "status": "PAID",
  "status_detail": "The payment was paid.",
  "status_code": "200",
  "order_id": "ord-221124442cd",
  "notification_url": "https://merchantsite.com/payments"
}
⚠️

Final status is payment-method-specific

For most wallets (Mercado Pago, Nequi, and NuPay, for example), the synchronous response to a DIRECT charge is the final status (PAID or REJECTED), as shown above. Yape (YE) is the exception: it always returns PENDING synchronously, and dLocal delivers the final status by webhook within seconds. Always confirm per-payment-method behavior in the relevant country section before implementing.

Tokenized wallets: Legacy

Legacy integration

The wallet object tokenization flow below is supported for existing merchants only and does not receive new feature development. New integrations must use the Enrollment API described above.

The enrollment and recurring charge are two separate API calls.

Step 1: Enrollment (REDIRECT)

Redirect the user to the wallet's website to authenticate and authorize future payments. Send wallet.save = true in the request. The asynchronous notification includes a wallet.token. Use that wallet.token for future payments without authenticating the user again. See The wallet object for the supported wallet fields.

Option A: Sale + verify flow

Enroll and charge simultaneously (wallet.verify: false, amount > 0). Use this option to charge the user and issue a wallet.token in the same flow.

{
  "amount": 26,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "PZ",
  "payment_method_flow": "REDIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "wallet": {
    "save": true,
    "verify": false,
    "capture": true
  },
  "device": {
    "type": "WEB"
  },
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "callback_url": "http://merchantsite.com/callback"
}
{
  "id": "R-4-41f8628f-b6ec-4c02-96d5-c5b03cac7cb0",
  "amount": 26,
  "currency": "BRL",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "country": "BR",
  "created_date": "2018-12-26T20:37:20.000+0000",
  "status": "PENDING",
  "status_detail": "The payment is pending.",
  "status_code": "100",
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "redirect_url": "https://pay.dlocal.com/gmf-apm/payments-redirect/M-0aa0cc00-..."
}
{
  "id": "R-4-41f8628f-b6ec-4c02-96d5-c5b03cac7cb0",
  "amount": 26,
  "currency": "BRL",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "country": "BR",
  "created_date": "2018-12-26T20:37:20.000+0000",
  "status": "PAID",
  "status_detail": "The payment was paid.",
  "status_code": "200",
  "order_id": "5346523564",
  "wallet": {
    "token": "<WALLET_TOKEN>"
  },
  "notification_url": "http://merchantsite.com/notifications"
}
⚠️

Payment failed, enrollment succeeded

The notification includes a wallet.token as long as the user authenticated successfully, regardless of whether dLocal approved the payment.

Option B: Verify flow

Enroll without charging (wallet.verify: true, amount: 0). dLocal verifies the wallet and issues a wallet.token without making a charge. Use this for free trials or deferred billing.

{
  "amount": 0,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "PZ",
  "payment_method_flow": "REDIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "wallet": {
    "save": true,
    "verify": true,
    "capture": false
  },
  "device": {
    "type": "WEB"
  },
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "callback_url": "http://merchantsite.com/callback"
}
{
  "id": "D-4-75c7473a-ab86-4e43-bd39-c840268747d3",
  "amount": 0,
  "currency": "BRL",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "country": "BR",
  "created_date": "2018-12-26T20:37:20.000+0000",
  "status": "PENDING",
  "status_detail": "The payment is pending",
  "status_code": "100",
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "redirect_url": "https://pay.dlocal.com/gmf-apm/payments-redirect/M-0aa0cc00-..."
}
{
  "id": "D-4-75c7473a-ab86-4e43-bd39-c840268747d3",
  "amount": 0,
  "status": "VERIFIED",
  "status_detail": "The wallet was verified.",
  "status_code": "700",
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "REDIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "wallet": {
    "token": "<WALLET_TOKEN>"
  },
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "created_date": "2018-12-26T20:37:20.000+0000"
}

Expect the asynchronous response at notification_url after the user approves the enrollment in the wallet provider.

Persist wallet.token for all future charges. Only store tokens from VERIFIED (700) or PAID (200) status. Tokens from rejected flows are invalid.

Step 2: Recurring charge (DIRECT)

Pay with a wallet.token. The request does not redirect the user.

⚠️

Recurring wallet payments

For recurring wallet payments in the Philippines and Indonesia, include the user's mobile number in the payer.phone field of the payment request.

{
    "amount": 10,
    "currency": "BRL",
    "country": "BR",
    "payment_method_id": "PZ",
    "payment_method_flow": "DIRECT",
    "payer": {
        "name": "Example Payer",
        "email": "[email protected]",
        "phone": "<PHONE_NUMBER>",
        "document": "<DOCUMENT_NUMBER>",
        "address": {
            "country": "BR",
            "state": "Example State",
            "city": "Example City",
            "zip_code": "<ZIP_CODE>",
            "street": "Example Street",
            "number": "123"
        }
    },
    "wallet": {
        "token": "<WALLET_TOKEN>"
    },
    "order_id": "fe32a6ef-3954-4b5f-8712-d1c1079beba3",
    "description": "test-wallet",
    "notification_url": "https://notifications.merchant.com"
}
{
  "id": "F-4-b302affe-e590-4b29-98cc-57ec2dd10592",
  "amount": 10,
  "currency": "BRL",
  "payment_method_id": "PZ",
  "payment_method_type": "WALLET",
  "payment_method_flow": "DIRECT",
  "country": "BR",
  "created_date": "2022-09-29T06:52:48.000+0000",
  "expiration_date": "2022-10-04T06:52:48.000+0000",
  "status": "PAID",
  "status_detail": "The payment was paid.",
  "status_code": "200",
  "order_id": "fe32a6ef-3954-4b5f-8712-d1c1079beba3",
  "description": "test-wallet",
  "notification_url": "https://notifications.merchant.com"
}
⚠️

Synchronous response

For most wallets, the synchronous response to a DIRECT charge is the final status (PAID or REJECTED). No need to wait for a notification. Yape (YE) is the exception: it returns PENDING synchronously, and dLocal delivers the final status by webhook within seconds.

Always confirm per-payment-method behavior in the relevant section.

📘

Device ID for Mercado Pago

Add the Device ID by following The DeviceId Object (for Mercado Pago only).

Include it in the wallet object. It improves fraud detection on Mercado Pago's side and can improve authorization rates.

Cancel a wallet.token

Cancel with the API

Call the cancel endpoint when a user unsubscribes, changes their payment method, or you need to cancel access programmatically.

See Cancel a wallet.token in the API reference section.

curl --request POST \
  --url "https://api.dlocal.com/payments/wallet/<WALLET_TOKEN>/cancel"
{
  "wallet": {
    "token": "<WALLET_TOKEN>"
  },
  "status": "CANCELLED",
  "status_detail": "The wallet token was cancelled."
}

Customer-initiated cancellation

Users can cancel a subscription or recurring authorization directly from their wallet app (Nequi, GCash, Mercado Pago, and Yape, for example). The behavior when this happens depends on which integration model you are using:

Enrollment API: The next DIRECT charge attempt returns status_code 328 when the enrollment has been cancelled. Handle 328 by stopping all future charge attempts against that enrollment ID and triggering a new enrollment flow for the user. You can also use the Cancel an enrollment endpoint proactively when a user unsubscribes on your side, so the enrollment is invalidated at dLocal before the next scheduled charge runs.

Legacy wallet token: The next DIRECT charge attempt using the cancelled wallet.token returns status_code 328 (invalid token). Handle 328 by stopping all future charge attempts and triggering a new enrollment flow. Always call the cancel token endpoint on your side when a user unsubscribes so your records stay in sync with the wallet provider.

Cancellation, whether merchant-initiated or customer-initiated, permanently invalidates the wallet.token or enrollment reference. Never retry a 328.

How wallet providers notify dLocal of user-initiated cancellations:

Not all wallet providers behave the same way when a user cancels access from within their app:

Proactive notification: The wallet provider notifies dLocal in real time. dLocal sends a webhook to your Payins Notification URL configured in dLocal's merchant dashboard to confirm that the authorization has been canceled. Listen for this webhook and update your records before the next scheduled charge.

Silent cancellation: The wallet provider does not notify dLocal. Your integration discovers the cancellation when the next DIRECT charge attempt returns status_code 328. Stop retrying and start a new enrollment flow.

Device type

Include device.type in all REDIRECT flows where the user is present, including both POST /payments and POST /enrollments. Wallet providers can use different experiences, such as deep links, app-to-app redirects, or push notifications. dLocal uses this field to route the best experience for each context without requiring integration changes.

Omit device.type from DIRECT charges that use a wallet.token or an enrollment.id reference. Those are customer-not-present requests.

ValueDescription
WEBThe user is on a desktop or mobile browser.
MOBILE_APPThe user is inside your native iOS or Android app.
{
  "amount": 26,
  "currency": "BRL",
  "country": "BR",
  "payment_method_id": "PZ",
  "payment_method_flow": "REDIRECT",
  "payer": {
    "name": "Example Payer",
    "email": "[email protected]",
    "document": "<DOCUMENT_NUMBER>"
  },
  "device": {
    "type": "MOBILE_APP"
  },
  "order_id": "5346523564",
  "notification_url": "http://merchantsite.com/notifications",
  "callback_url": "http://merchantsite.com/callback"
}

For payment methods where device.type is already mandatory, such as Yape, see the payment-method-specific sections for full behavior details.

Sandbox testing

Use the description field in your request body to control payment behavior in the sandbox environment.

Enrollment flows (REDIRECT)

description valueBehavior
OmittedReturns PENDING. Use the mock playground UI to manually approve or reject. Recommended for UX testing.
"100:approved"Returns PENDING, then auto-sends a PAID (or VERIFIED / ACTIVE) webhook after ~60 seconds. Recommended for automated testing.
"100:rejected"Returns PENDING, then auto-sends a REJECTED webhook after ~60 seconds.

Recurring charges (DIRECT)

description valueBehavior
"200"Returns PAID immediately.
"300"Returns REJECTED immediately.
⚠️

Mock server vs. real provider environment

By default, all sandbox payments are routed through dLocal's mock server, which provides stable, predictable behavior across all wallet payment methods. If you need to test against the actual sandbox environment of a specific wallet provider to validate provider-side behavior or UX, check with your assigned dLocal TAM. Some providers require additional configuration or have limited sandbox availability.