Make a test payment

Learn how to simulate payments using dLocal’s sandbox environment before going live.

The dLocal Sandbox is a test environment that mirrors the production system. It allows you to safely simulate payments, check API behavior, and trigger webhooks without processing real transactions.

In Test mode, you can monitor test transactions through the Merchant Dashboard. You can manage both sandbox and production from the same account.

Step 1: Requirements to start testing

Step 2: How does it work?

Sandbox URL

URL Selector with Static Display
Sandbox URL

Sandbox tools URL

For certain payments, such as cash or refunds, it is necessary to force the status. That's why you need to use this specific one:

Sandbox tools URL

Steps to test a payment

  1. Set up authentication headers.
  2. Build the API request you want to simulate using test data.
  3. Send the request to the sandbox endpoint and simulate different responses.
  4. Check the response and your webhook listener.

Simulate payment status

In Sandbox, you can control the payment result by passing a status code in the request body's description field.

"description": "302"

Sample description values to simulate card responses

descriptionSimulated statusMeaning
"200"PAIDPayment approved
"300"REJECTEDGeneric rejection
"302"REJECTEDInsufficient funds

Sample description values to simulate cash payments

statusMeaning
"PAID"Payment approved
"REJECTED"Generic rejection
"ERROR"Generic error

All possible status codes are listed in the API Reference. For specific operations like payments or refunds, you’ll find detailed status codes in their respective sections:

Step 3: Test payments

Below are common test cases using the sandbox. This is useful to test status-code-based UI messaging or error categorization.

General payment example

Refer to the example below and modify the relevant data to build and test payment requests in the sandbox environment. Modifies the description field in the payment request to trigger specific outcomes.

curl -X POST \
   -H 'X-Date: {x-date}' \
   -H 'X-Login: {x-login}' \
   -H 'X-Trans-Key: {x-trans-key}' \
   -H 'Content-Type: application/json' \
   -H 'X-Version: 2.1' \
   -H 'User-Agent: MerchantTest / 1.0 ' \
   -H 'Authorization: V2-HMAC-SHA256, Signature: {Signature}' \
   -d '{body}'
    https://sandbox.dlocal.com/payments

{
  "amount": 100,
  "currency": "USD",
  "country": "BR",
  "payment_method_id": "CARD",
  "payment_method_flow": "DIRECT",
  "payer":{
    "name": "Thiago Gabriel",
    "email": "[email protected]",
    "document": "53033315550",
    "user_reference": "12345",
    "address": {
      "state": "Rio de Janeiro",
      "city": "Volta Redonda",
      "zip_code": "27275-595",
      "street": "Servidao B-1",
      "number": "1106"
    }
  },
  "order_id": "657434343",
  "description": "200",
  "notification_url": "http://merchantsite.com/notifications"
}

Test scenarios


Payment with credit card: approved


To test an approved payment with status PAID, set the description field to 200.

Use the Create a payment API endpoint if you want to customize the example.


Example request

curl -X POST \
   -H 'X-Date: {x-date}' \
   -H 'X-Login: {x-login}' \
   -H 'X-Trans-Key: {x-trans-key}' \
   -H 'Content-Type: application/json' \
   -H 'X-Version: 2.1' \
   -H 'User-Agent: MerchantTest / 1.0 ' \
   -H 'Authorization: V2-HMAC-SHA256, Signature: {Signature}' \
   -d '{body}'
    https://sandbox.dlocal.com/payments

{
  "amount": 100,
  "currency": "USD",
  "country": "BR",
  "payment_method_id": "CARD", // Must be "CARD" for card payments
  "payment_method_flow": "DIRECT",
  "payer":{
    "name": "Thiago Gabriel",
    "email": "[email protected]",
    "document": "53033315550",
    "user_reference": "12345",
    "address": {
      "state": "Rio de Janeiro",
      "city": "Volta Redonda",
      "zip_code": "27275-595",
      "street": "Servidao B-1",
      "number": "1106"
    }
  },
  "order_id": "657434343",
  "description": "200", // Use "200" to simulate approved (PAID) payment
  "notification_url": "http://merchantsite.com/notifications"
}

Expected response

The response you should expect for the specified properties in this test:

{
  "status" : "PAID",
  "status_code" : "200",
  "status_detail" : "The payment was paid.",
}


Payment with credit card: rejected


To test a rejected payment with status REJECTED, set the description field to 300.

Example request

curl -X POST \
   -H 'X-Date: {x-date}' \
   -H 'X-Login: {x-login}' \
   -H 'X-Trans-Key: {x-trans-key}' \
   -H 'Content-Type: application/json' \
   -H 'X-Version: 2.1' \
   -H 'User-Agent: MerchantTest / 1.0 ' \
   -H 'Authorization: V2-HMAC-SHA256, Signature: {Signature}' \
   -d '{body}'
    https://sandbox.dlocal.com/payments

{
  "amount": 100,
  "currency": "USD",
  "country": "BR",
  "payment_method_id": "CARD", // Must be "CARD" for card payments.
  "payment_method_flow": "DIRECT",
  "payer":{
    "name": "Thiago Gabriel",
    "email": "[email protected]",
    "document": "53033315550",
    "user_reference": "12345",
    "address": {
      "state": "Rio de Janeiro",
      "city": "Volta Redonda",
      "zip_code": "27275-595",
      "street": "Servidao B-1",
      "number": "1106"
    }
  },
  "order_id": "657434343",
  "description": "300", // Use "300" to simulate rejected (REJECTED) payment.
  "notification_url": "http://merchantsite.com/notifications"
}

Expected response

The response you should expect for the specified properties in this test:

{
  "status" : "REJECTED",
  "status_code" : "300",
  "status_detail" : "The payment was rejected.",
}

Direct cash payment: approve or expire


For direct cash payments, you can manually set the final status using the /sandbox-tools/payments endpoint. It can be tested by either forcing an approval (PAID) or an expiration (REJECTED).

Visit the Coverage page to explore different payment methods.


Payment example request

curl -X POST \
   -H 'X-Date: {x-date}' \
   -H 'X-Login: {x-login}' \
   -H 'X-Trans-Key: {x-trans-key}' \
   -H 'Content-Type: application/json' \
   -H 'X-Version: 2.1' \
   -H 'User-Agent: MerchantTest / 1.0 ' \
   -H 'Authorization: V2-HMAC-SHA256, Signature: {Signature}' \
   -d '{body}'
    https://sandbox.dlocal.com/payments

{
  "amount": 100,
  "currency": "USD",
  "country": "BR",
  "payment_method_id": "BL", // Must be the ID of a direct cash payment method.
  "payment_method_flow": "DIRECT",
  "payer":{
    "name": "Thiago Gabriel",
    "email": "[email protected]",
    "document": "53033315550",
    "user_reference": "12345",
    "address": {
      "state": "Rio de Janeiro",
      "city": "Volta Redonda",
      "zip_code": "27275-595",
      "street": "Servidao B-1",
      "number": "1106"
    }
  },
  "order_id": "657434343",
  "notification_url": "http://merchantsite.com/notifications"
}

Final status example request

curl -X POST \
   -H 'X-Date: {x-date}' \
   -H 'X-Login: {x-login}' \
   -H 'X-Trans-Key: {x-trans-key}' \
   -H 'Content-Type: application/json' \
   -H 'X-Version: 2.1' \
   -H 'User-Agent: MerchantTest / 1.0 ' \
   -H 'Authorization: V2-HMAC-SHA256, Signature: {Signature}' \
   -d '{body}'
    https://sandbox.dlocal.com/sandbox-tools/payments

{
   "payment_id" : "PAY4334346343", // Get the payment ID from the payment creation response.
   "status": "PAID" // Use "PAID" to simulate an approved payment, or "REJECTED" to simulate a rejected payment.
}

Expected response

In both cases, if you receive a code 200, it means your PAID or REJECTED request is successful. Also, this will trigger a notification with the new status.

If payment_id doesn’t exist, you will receive a 404 response

{
   "code": 0,
   "status": "ERROR",
   "message": "404 {\"code\":4000,\"message\":\"Payment not found\"}"
}

If payment_id is not in PENDING status, you will receive a 400 response.

{
   "code": 5002,
   "message": "Payment D-4-fdb6fe34-de6c-4f66-8895-ef87a1918b29 has not status PENDING. Actual status: PAID"
}


Refund for cash and bank transfer


To test refund flows, use the /sandbox-tools/refunds/update-status endpoint to update the refund status.

For cash and bank transfer refunds, you will get a PENDING status when calling the Make a refunds API.

To test other statuses, you can use the below PATCH method to force a refund to update to another status (SUCCESS, REJECTED, or CANCELLED). Then, you will be able to receive a refund notification.


Example request

curl --location --request PATCH 'https://sandbox.dlocal.com/sandbox-tools/refunds/update-status' \
--header 'X-Login: {x-login}' \
--header 'X-Trans-Key: {x-trans-key}' \
--header 'Content-Type: application/json' \
--data-raw '

{
  "id_refund": "R-462778-e60039e7-ed75-4cd5-ad47-fc7f05fa6347",
  "status": "SUCCESS" 
}'

Expected response

You will get an HTTP code 200 with the below response, which means the refund status is updated and will trigger a notification with the new status.

{
 "code": 0,
 "status": "ERROR",
 "message": "404 {\"code\":4000,\"message\":\"Payment not found\"}"
}

If the refund is not in pending status, you will get the below response with HTTP code 400.

{
 "code": 5002,
 "message": "Payment D-4-fdb6fe34-de6c-4f66-8895-ef87a1918b29 has not status PENDING. Actual status: PAID"
}

What’s Next

Once your integration is tested, move on to configuring the initial settings needed for production.