Quick start

Do docker run a um webhook na sua máquina e um mês pulado. Cada chamada abaixo roda como está escrita contra um container novo.

  1. Suba

    Fixe a chave de API, ou um volume novo imprime outra no boot (no shell, aspas simples preservam o $). Suba o relógio num modo virtual, senão ele segue a máquina e se recusa a pular.

    docker run --rm -p 45445:45445 \
      -e 'ASAAS_API_KEY=$aact_hmlg_local' \
      -e CLOCK_MODE=VIRTUAL_FLOWING \
      -e WEBHOOK_LOCALHOST_REWRITE=host.docker.internal \
      --add-host host.docker.internal:host-gateway \
      ghcr.io/instituto-ama/asaas-mock:latest

    WEBHOOK_LOCALHOST_REWRITE faz um webhook registrado como http://localhost:4000/… chegar na sua máquina a partir do container. O painel fica em http://localhost:45445.

  2. Aponte sua aplicação

    Trocar do sandbox para o mock é trocar a URL base. Os caminhos, corpos, headers e erros são os do Asaas.

    - ASAAS_BASE_URL=https://api-sandbox.asaas.com/v3
    + ASAAS_BASE_URL=http://localhost:45445/v3
      ASAAS_API_KEY=$aact_hmlg_local
  3. Crie um cliente

    curl localhost:45445/v3/customers \
      -H 'access_token: $aact_hmlg_local' -H 'content-type: application/json' \
      -d '{"name":"Maria Souza","cpfCnpj":"24971563792","email":"maria@example.com","mobilePhone":"11987654321"}'
    # → {"object":"customer","id":"cus_526128665490",…}
  4. Registre o seu webhook

    Pelo /v3/webhooks de verdade. As regras são as do Asaas: o authToken precisa ter de 32 a 255 caracteres, e o seu endpoint precisa responder HTTP 200.

    curl localhost:45445/v3/webhooks \
      -H 'access_token: $aact_hmlg_local' -H 'content-type: application/json' \
      -d '{"name":"my-app","url":"http://localhost:4000/webhooks/asaas","email":"dev@example.com",
           "enabled":true,"interrupted":false,"apiVersion":3,"sendType":"SEQUENTIALLY",
           "authToken":"whsec_local_demo_token_0123456789abcdef",
           "events":["PAYMENT_CREATED","PAYMENT_CONFIRMED","PAYMENT_RECEIVED","PAYMENT_OVERDUE"]}'

    Cada entrega leva o header asaas-access-token com o seu token. GET /_admin/webhooks/deliveries mostra cada tentativa com a resposta do seu endpoint.

  5. Cobre e pague

    Uma cobrança Pix vai direto para RECEIVED quando paga. Pague como o pagador pagaria, na página do invoiceUrl (um QR code de verdade), ou com a chamada do próprio sandbox:

    curl localhost:45445/v3/payments \
      -H 'access_token: $aact_hmlg_local' -H 'content-type: application/json' \
      -d '{"customer":"cus_526128665490","billingType":"PIX","value":89.9,"dueDate":"2026-11-10"}'
    
    curl -X POST localhost:45445/v3/sandbox/payment/pay_…/confirm -H 'access_token: $aact_hmlg_local'
    # → o seu endpoint recebe PAYMENT_CREATED e depois PAYMENT_RECEIVED
  6. Pule o tempo

    Cada dia simulado roda um tick completo: assinaturas cobram, cobranças em aberto vencem, o cartão cai, os webhooks disparam.

    curl localhost:45445/_admin/clock                     # onde o relógio está
    curl -X POST localhost:45445/_admin/clock/advance \
      -H 'content-type: application/json' -d '{"days": 32}'
    curl -X POST localhost:45445/_admin/clock/set \
      -H 'content-type: application/json' -d '{"date": "2027-01-01"}'

    Os casos de uso põem isso para trabalhar: um cartão que cai em D+32, um boleto pago com atraso, uma assinatura um ano à frente.

  7. No seu compose

    services:
      asaas:
        image: ghcr.io/instituto-ama/asaas-mock:0.11.0   # fixe uma versão, ou :latest
        ports:
          - '45445:45445'
        environment:
          # `$$` é um `$` literal no compose.
          ASAAS_API_KEY: '$$aact_hmlg_local'
          WEBHOOK_LOCALHOST_REWRITE: host.docker.internal
          CLOCK_MODE: VIRTUAL_FLOWING
        extra_hosts:
          - 'host.docker.internal:host-gateway'   # Linux
        volumes:
          - asaas-data:/data
    volumes:
      asaas-data:

    De um serviço na mesma rede, o mock fica em http://asaas:45445/v3. Coloque um serviço whatsapp, um sms e um mailpit ao lado e ele acha os três sozinho, como na página do Asaas.

  8. No CI

    Use CLOCK_MODE=VIRTUAL_FROZEN e nenhum volume: o relógio só anda quando o teste manda, e toda execução começa do mesmo estado. O teste fica parecido com a regra de negócio que ele verifica:

    # cria a cobrança → espera PENDING
    # avança 1 dia depois do vencimento → espera o pedido marcado como vencido
    # confirma o pagamento → espera o handler do webhook ter baixado o pedido