Error 400 (Bad Request)

What should I do when I see this error in the Asaas Webhook logs?

The 400 Bad Request error indicates that the Webhook request reached the endpoint, but was rejected while validating or interpreting the received content.

In this scenario, mainly check the parser, the validations, and the structure expected by your application.

Main causes

The error may occur when the application:

  • expects fields that do not exist in the payload;
  • treats optional or null fields as required;
  • cannot deserialize the JSON;
  • rejects unknown attributes;
  • has overly restrictive validations;
  • tries to convert values to incompatible types;
  • only accepts certain events;
  • uses fixed structures that do not allow the payload to evolve.
🚧

Attention

If not fixed, the 400 error can completely interrupt synchronization between your application and Asaas.

Check optional and null fields

Not every payment belongs to a subscription. An application may expect:

{
  "payment": {
    "subscription": "sub_123"
  }
}

But receive:

{
  "payment": {
    "subscription": null
  }
}

If payment.subscription is treated as required, the endpoint may reject the event with HTTP 400.

Only validate as required the fields needed for your business rule, and handle the null values expected for the resource.

Accept new attributes in the payload

An application may be prepared to receive:

{
  "id": "evt_xxx",
  "event": "PAYMENT_RECEIVED"
}

The payload may receive new attributes over time:

{
  "id": "evt_xxx",
  "event": "PAYMENT_RECEIVED",
  "newAttribute": "value"
}

The parser should not reject the request just because it received an attribute that the application does not use yet.

📘

Important

The Webhook payload may evolve over time. Your system must be prepared to accept new attributes without throwing exceptions.

How to identify the cause

1. Check the Webhook Logs

Go to Webhook Logs and find the attempt that returned HTTP 400.

Check:

  • the payload sent;
  • the time of the attempt;
  • the HTTP code returned;
  • the number of resends.

2. Compare the payload with the corresponding event

Confirm that the application is prepared to handle:

  • optional attributes;
  • null fields;
  • attributes not yet used by the integration;
  • the different events configured in the Webhook.

See the specific event page in Webhook Events.

3. Review your application logs

Use the attempt time recorded in the Webhook Logs to find the request in your system.

Check at which stage the rejection occurred, such as:

  • deserialization;
  • field validation;
  • type conversion;
  • event validation;
  • business rule executed during the request.

Fix and validate the endpoint

After identifying the cause:

  1. adjust the parser or validation responsible for the HTTP 400;
  2. allow optional fields, null values, and unknown attributes when applicable;
  3. persist the event before starting long-running processing;
  4. respond with HTTP 200 after confirming persistence;
  5. run additional rules asynchronously.

Webhooks follow the at least once model. Use the event id to prevent a retry from causing duplicate processing.

See how to implement idempotency in Webhooks.

Fix flow

%%{init: {"flowchart": {"nodeSpacing": 28,"rankSpacing": 32,"diagramPadding": 8,"padding": 10}}}%%
flowchart TD
    A["Identify HTTP 400"] --> B["Check Webhook Logs"]
    B --> C["Check the payload"]
    C --> D["Fix parser or validations"]
    D --> E["Test again"]
    E --> F{"Is the queue interrupted?"}

    F --> FSim(("Yes"))
    F --> FNao(("No"))

    FSim --> G["Reactivate the queue"]
    FNao --> H["Wait for a new delivery"]

    G --> I["Confirm HTTP 200"]
    H --> I

    classDef inicio fill:#DBEAFE,stroke:#2563EB,color:#1E3A8A,stroke-width:3px,font-size:17px
    classDef decisao fill:#FEF3C7,stroke:#D97706,color:#78350F,stroke-width:3px,font-size:17px
    classDef validacao fill:#E0F2FE,stroke:#0284C7,color:#0C4A6E,stroke-width:2px,font-size:17px
    classDef sucesso fill:#DCFCE7,stroke:#16A34A,color:#14532D,stroke-width:3px,font-size:17px
    classDef respostaSim fill:#22C55E,stroke:#15803D,color:#FFFFFF,stroke-width:3px,font-size:16px
    classDef respostaNao fill:#EF4444,stroke:#B91C1C,color:#FFFFFF,stroke-width:3px,font-size:16px

    class A inicio
    class B,C,D,E,G,H validacao
    class F decisao
    class I sucesso

    class FSim respostaSim
    class FNao respostaNao

    linkStyle default stroke:#94A3B8,stroke-width:2px
    linkStyle 5 stroke:#22C55E,stroke-width:4px
    linkStyle 6 stroke:#EF4444,stroke-width:4px

What happens while the error persists

Each HTTP 400 response is considered a delivery failure.

With consecutive failures:

  • the same event may be sent again;
  • the configuration enters the progressive penalty mechanism;
  • after 15 consecutive failures, the Webhook queue is interrupted;
  • while it is interrupted, new events are stored and are no longer sent.

If the queue is already interrupted, fix the error before reactivating it.

Understand Queue penalty.

See how to reactivate an interrupted queue.

Next steps


Did this page help you?