Skip to content

Full integration example ​

This guide walks through the complete flow of a sale -- from authentication to payment confirmation -- using the sandbox environment with ready-to-use examples you can copy and run.

TIP

All examples use sandbox URLs. For production, replace sandboxappmax with appmax in the URLs.

What we will build ​

Authenticate -> Collect IP -> Create customer -> Create order -> Pay -> Confirm

By the end of this guide you will have completed a full transaction in the sandbox.

Prerequisites ​


1. Authenticate ​

Obtain a Bearer token using the merchant's credentials.

bash
curl --request POST \
     --url https://auth.sandboxappmax.com.br/oauth2/token \
     --header 'Content-Type: application/x-www-form-urlencoded' \
     --data-urlencode 'grant_type=client_credentials' \
     --data-urlencode 'client_id=SEU_CLIENT_ID' \
     --data-urlencode 'client_secret=SEU_CLIENT_SECRET'
json
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Save the access_token. It will be used in all subsequent calls as Bearer YOUR_TOKEN. The token expires in 1 hour.


2. Collect the customer's IP ​

Before creating the customer, you must collect the IP using Appmax JS. Include the script on your checkout page:

html
<!DOCTYPE html>
<html>
<head>
  <title>Checkout</title>
</head>
<body>
  <form id="customer-form" data-appmax-customer>
    <input type="text" name="first_name" placeholder="Nome" required />
    <input type="text" name="last_name" placeholder="Sobrenome" required />
    <input type="email" name="email" placeholder="E-mail" required />
    <input type="text" name="phone" placeholder="Telefone" required />
    <button type="submit">Continuar</button>
  </form>

  <script src="https://scripts.sandboxappmax.com.br/appmax.min.js"></script>
  <script>
    let clienteIP = null;

    window.AppmaxScripts.init(
      function onSuccess(data) {
        clienteIP = data.ip;
        console.log('IP coletado:', clienteIP);
      },
      function onError(err) {
        console.error('Erro ao coletar IP:', err);
      }
    );

    document.getElementById('customer-form').addEventListener('submit', function(e) {
      e.preventDefault();
      if (!clienteIP) {
        alert('Aguarde a coleta do IP');
        return;
      }
      // Send form data + clienteIP to your backend
      enviarParaBackend({
        first_name: this.first_name.value,
        last_name: this.last_name.value,
        email: this.email.value,
        phone: this.phone.value,
        ip: clienteIP
      });
    });
  </script>
</body>
</html>

WARNING

In the sandbox, if the IP is not available, use 127.0.0.1 for testing. In production, the real IP is required.


3. Create the customer ​

On your backend, send the customer data to the API. The combination of first_name + last_name + email + phone + ip is the unique key -- if a match already exists, the customer is updated.

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/customers \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "first_name": "Junior",
  "last_name": "Almeida",
  "email": "[email protected]",
  "phone": "51983655100",
  "ip": "127.0.0.1",
  "document_number": "25226493029",
  "address": {
    "postcode": "91520270",
    "street": "Rua Francisco Carneiro da Rocha",
    "number": "582",
    "complement": "Casa",
    "district": "Moinhos de Ventos",
    "city": "Porto Alegre",
    "state": "RS"
  }
}'
json
{
  "data": {
    "customer": {
      "id": 2023
    }
  }
}

Save data.customer.id -- this is the customer_id that will be used in the order.


4. Create the order ​

Link the order to the customer. Values are in cents (R$ 123.00 = 12300).

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/orders \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "customer_id": 2023,
  "products": [
    {
      "sku": "LIVRO-001",
      "name": "Livro de receitas",
      "quantity": 1,
      "unit_value": 12300,
      "type": "digital"
    }
  ],
  "shipping_value": 0,
  "discount_value": 0
}'
json
{
  "data": {
    "order": {
      "id": 3531,
      "status": "pendente"
    }
  }
}

Save data.order.id -- this is the order_id that will be used in the payment. The status starts as pendente.


5. Process the payment ​

Choose one of the methods below. In the sandbox, use the test card 4000000000000010 to simulate a successful payment.

There are two approaches: via token (recommended) or via Appmax JS. This example uses tokenization:

Step 1 -- Tokenize the card:

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/payments/tokenize \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "payment_data": {
    "credit_card": {
      "number": "4000000000000010",
      "cvv": "123",
      "expiration_month": "12",
      "expiration_year": "28",
      "holder_name": "Junior Almeida"
    }
  }
}'
json
{
  "data": {
    "token": "422146c7523a46119d6073ea56193913"
  }
}

Step 2 -- Pay with the token:

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/payments/credit-card \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "order_id": 3531,
  "customer_id": 2023,
  "payment_data": {
    "credit_card": {
      "token": "422146c7523a46119d6073ea56193913",
      "holder_document_number": "25226493029",
      "holder_name": "Junior Almeida",
      "installments": 1,
      "soft_descriptor": "MINHALOJA"
    }
  }
}'
json
{
  "data": {
    "order": {
      "id": 3531,
      "status": "autorizado"
    },
    "payment": {
      "method": "creditcard",
      "installments": 1,
      "paid_at": "2025-03-15 14:30:00"
    },
    "upsell_hash": "4000114202503117156088040208561001715608804"
  }
}

The autorizado status indicates the payment was accepted and is undergoing anti-fraud analysis. Wait for the order_approved webhook for confirmation.

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/payments/pix \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "order_id": 3531,
  "payment_data": {
    "pix": {
      "document_number": "25226493029"
    }
  }
}'
json
{
  "data": {
    "order": {
      "id": 3531,
      "status": "pendente"
    },
    "pix": {
      "qr_code": "data:image/png;base64,iVBORw0KGgoAAAANS...",
      "emv_code": "00020126580014br.gov.bcb.pix0136a1b2c3d4...",
      "expires_at": "2025-03-15 15:30:00"
    }
  }
}

Display the qr_code as an image and the emv_code as copyable text. Wait for the order_paid_by_pix webhook for confirmation.

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/payments/boleto \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "order_id": 3531,
  "payment_data": {
    "boleto": {
      "document_number": "25226493029"
    }
  }
}'
json
{
  "data": {
    "order": {
      "id": 3531,
      "status": "pendente"
    },
    "boleto": {
      "pdf_url": "https://boleto.sandboxappmax.com.br/pdf/abc123...",
      "digitable_line": "23793.38128 60000.000003 00000.000400 1 84340000012300",
      "due_date": "2025-03-22"
    }
  }
}

Offer the pdf_url as a download button and the digitable_line as copyable text. Wait for the order_paid webhook when the boleto is settled.


6. Confirm the payment ​

Confirmation is asynchronous. There are two ways to know the payment was approved:

Your endpoint will receive a POST when the status changes:

json
{
  "event": "order_approved",
  "event_type": "order",
  "data": {
    "order": {
      "id": 3531,
      "status": "aprovado",
      "total_paid": 12300
    },
    "customer": {
      "id": 2023,
      "name": "Junior Almeida",
      "email": "[email protected]"
    },
    "payment": {
      "method": "creditcard",
      "installments": 1,
      "paid_at": "2025-03-15 14:30:00"
    }
  }
}

Respond with HTTP 200 to acknowledge receipt.

Via query (polling) ​

If you need to check the status manually:

bash
curl --request GET \
     --url https://api.sandboxappmax.com.br/v1/orders/3531 \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json'
json
{
  "data": {
    "order": {
      "id": 3531,
      "status": "aprovado",
      "total_paid": 12300,
      "amounts": {
        "sub_total": 12300,
        "shipping_value": 0,
        "discount": 0,
        "installment_fee": 0
      }
    },
    "customer": {
      "id": 2023,
      "name": "Junior Almeida",
      "email": "[email protected]"
    },
    "payment": {
      "method": "creditcard",
      "installments": 1,
      "paid_at": "2025-03-15 14:30:00"
    }
  }
}

See all possible statuses.


7. After payment ​

Physical products: register the tracking code ​

To release the merchant's withdrawals, update the order with the tracking code:

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/orders/shipping-tracking-code \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "order_id": 3531,
  "shipping_tracking_code": "BR123456789XX"
}'

Refund (if needed) ​

To request a full refund:

bash
curl --request POST \
     --url https://api.sandboxappmax.com.br/v1/orders/refund-request \
     --header 'Authorization: Bearer YOUR_TOKEN' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "order_id": 3531,
  "type": "total",
  "value": 12300
}'

Flow summary ​

StepEndpointResult
AuthenticatePOST /oauth2/tokenaccess_token
Create customerPOST /v1/customerscustomer_id
Create orderPOST /v1/ordersorder_id (status: pendente)
Tokenize cardPOST /v1/payments/tokenizetoken
PayPOST /v1/payments/credit-cardstatus: autorizado
ConfirmWebhook order_approvedstatus: aprovado
TrackingPOST /v1/orders/shipping-tracking-codeTracking linked

Testing error scenarios ​

Use card 4000000000000028 to simulate a payment failure. The API will return:

json
{
  "error": {
    "message": "Payment not authorized"
  }
}

See more test cards in the credit card documentation.


Next steps ​