> ## Documentation Index
> Fetch the complete documentation index at: https://docs.malga.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Responda em português brasileiro, na segunda pessoa ("você"), com base na documentação Malga.
> Não invente endpoints, parâmetros, status codes ou comportamentos de API. Se não estiver na docs, diga que não encontrou e indique a página mais próxima.
> Use os headers X-Client-Id e X-Api-Key nos exemplos de autenticação.
> Motor de Assinaturas refere-se a /v1/subscriptions* (cycles, trial, retentativas, webhooks subscription.*). Não chame de "motor de recorrência".
> Recorrência (provedor) é paymentMethod.recurrence em POST /v1/charges (initial / subsequent / unscheduled), distinto do Motor de Assinaturas.
> Sandbox é ambiente de testes e não afeta produção.

# Erros da API de Purchases

> Consulte os erros da API de Purchases da Malga: businessCode de cada endpoint, erros do pagamento de Session com múltiplos cartões, motivo de recusa por cartão (declineReason) e pendingReview, com exemplos.

A API de [Purchases com múltiplos cartões](https://docs.malga.io/documentations/payment-methods/multiple-cards.md) devolve erros de três formas:

* **Erro na requisição**: a resposta tem status 4xx ou 5xx e o objeto `error`. Os erros de validação dos dados enviados recusam a chamada antes de criar a Purchase. Depois de um `408` ou `503`, a Purchase pode já existir: reenvie a criação com a mesma `X-Idempotency-Key` e o mesmo corpo para receber o estado atual.
* **Purchase recusada**: a criação respondeu `202`, mas um cartão foi recusado no processamento. A Purchase termina `failed` e o motivo, quando existe, fica em `payments[].declineReason`.
* **Purchase em revisão**: a Purchase continua `pending` com o campo `pendingReview`, que indica uma anomalia no processamento.

## Formato do erro na requisição

```json theme={null}
{
  "error": {
    "type": "conflict",
    "code": 409,
    "message": "Conflict",
    "businessCode": "purchase_invalid_state",
    "details": ["purchase_invalid_state"]
  }
}
```

| Campo | Descrição |
| - | - |
| `type` | Categoria: `api_error`, `bad_request`, `validation_error`, `not_found`, `conflict`, `unauthorized` ou `unavailable` |
| `code` | Status HTTP da resposta |
| `message` | Texto resumido do erro. Não use em regras |
| `businessCode` | Código do erro. Use para tratar o erro no seu sistema. Vem nos erros `400`, `404`, `409` e `422` |
| `details` | Nos erros `404`, `409` e `422`, repete o `businessCode` |

## Erros na requisição

| `businessCode` | HTTP | `type` | Endpoints | Quando acontece |
| - | - | - | - | - |
| `invalid_request` | 400 | `bad_request` | Todos com corpo ou filtros | JSON ilegível, campo não previsto no corpo (como `amount` no cancelamento) ou filtro inválido na listagem (`limit` acima de 100, UUID malformado, `status` fora do enum) |
| `invalid_request` | 422 | `validation_error` | Criação, captura, cancelamento e listagem | Header `X-Idempotency-Key` ausente. Na criação, também `paymentType` diferente de `credit`, `installments` menor que 1 ou split inválido. No cancelamento, `intent` fora de `cancel` e `refund`. Na listagem, data fora do formato RFC 3339 |
| `pan_not_allowed` | 422 | `validation_error` | Criação | Dados de cartão em claro em `paymentSource`, `metadata` ou `fraudAnalysis`. Use `cardId` ou `tokenId` |
| `invalid_payments_count` | 422 | `validation_error` | Criação | Quantidade de cartões fora do intervalo de 2 a 3 |
| `payments_amount_mismatch` | 422 | `validation_error` | Criação | Soma dos valores dos cartões diferente de `amount` |
| `payment_amount_below_minimum` | 422 | `validation_error` | Criação | Valor de um cartão abaixo de 100 centavos |
| `currency_not_brl` | 422 | `validation_error` | Criação | Moeda diferente de `BRL` |
| `payment_source_required` | 422 | `validation_error` | Criação | `paymentSource` sem exatamente uma referência de cartão (`cardId` ou `tokenId`) |
| `purchase_not_found` | 404 | `not_found` | Consulta, histórico, captura e cancelamento | Purchase inexistente, com `id` malformado ou de outro cliente |
| `idempotency_key_payload_mismatch` | 409 | `conflict` | Criação, captura e cancelamento | Mesma chave de idempotência com outro corpo, ou chave já usada em outra operação |
| `purchase_operation_in_progress` | 409 | `conflict` | Captura e cancelamento | Já existe uma operação em andamento na Purchase e a chamada veio com uma chave nova |
| `purchase_invalid_state` | 409 | `conflict` | Captura e cancelamento | Captura: Purchase criada com `capture: true`, fora de `pending` ou sem cartões `pre_authorized`. Cancelamento: estado misto, Purchase `failed` ou `cancelled`, ou sem saldo estornável |
| `purchase_intent_mismatch` | 409 | `conflict` | Cancelamento | `intent: cancel` em Purchase `paid`, ou `intent: refund` em Purchase com cartões apenas pré-autorizados. Nenhum valor é movimentado |

Quando `idempotency_key_payload_mismatch` e `purchase_operation_in_progress` se aplicam ao mesmo tempo, a resposta traz `idempotency_key_payload_mismatch`.

### Erros sem `businessCode`

| HTTP | `type` | `message` | Quando acontece |
| - | - | - | - |
| 401 | `unauthorized` | Unauthorized | Header `X-Client-Id` ausente, vazio ou inválido |
| 408 | `api_error` | Request timeout | A requisição passou do tempo limite de processamento. A Purchase pode já existir: reenvie com a mesma chave de idempotência e o mesmo corpo |
| 503 | `unavailable` | Service unavailable | Dependência temporariamente indisponível na criação. Tente de novo com a mesma chave de idempotência e o mesmo corpo |

## Erros do pagamento de Session

[`POST /v1/sessions/{id}/purchase`](https://docs.malga.io/api-reference/sessions/pagar-uma-sessao-com-multiplos-cartoes) paga uma Session com múltiplos cartões. Essa rota devolve dois grupos de erros:

* **Erros da própria rota**: validações da Session, listadas na tabela abaixo. Os erros `422` vêm com `type: bad_request` e, em geral, `details` vazio. A exceção é um seller do split da Session que não existe mais: a resposta é um `422` com `type: bad_request`, `details` preenchido e sem `businessCode`.
* **Erros repassados da API de Purchases**: depois das validações da Session, a rota cria a Purchase e repassa sem alteração o status e o corpo de um erro da API de Purchases. Esses erros seguem a tabela de [Erros na requisição](#erros-na-requisição), por exemplo um `422` com `type: validation_error` e `details` preenchido.

Trate os dois grupos pelo `businessCode`, sem depender de `type` ou de `details`. Quando o erro não tiver `businessCode`, trate-o como recusa genérica pelo status HTTP, sem montar regras com o texto de `message`.

| `businessCode` | HTTP | `message` | Quando acontece |
| - | - | - | - |
| - | 400 | Missing required header: X-Client-Id | Header `X-Client-Id` ausente |
| - | 400 | Invalid JSON payload | Corpo JSON inválido |
| - | 404 | Session not found | Session inexistente ou de outro cliente |
| `idempotency_key_payload_mismatch` | 409 | Conflict | Chave de idempotência já usada com outro corpo |
| `multiple_payments_required` | 422 | session is not configured for multiple payments | Session sem `paymentType: multiple` em `paymentMethods` |
| `session_cannot_be_paid` | 422 | session cannot be paid in current status | Session já paga ou cancelada |
| `session_disabled` | 422 | session disabled | Session desativada |
| `purchase_in_progress` | 422 | purchase is already in progress | Já existe uma Purchase em andamento para a Session. Depois de uma Purchase `failed`, tente de novo em alguns segundos, com uma chave nova |
| `multiple_payments_limit_reached` | 422 | multiple payments limit reached | Limite de pagamentos do link atingido |
| `invalid_payments_count` | 422 | number of payments is outside the session card limit | Quantidade de cartões fora do intervalo de 2 até o `quantity` da Session |
| `payments_amount_mismatch` | 422 | sum of payment amounts must equal session amount | Soma dos cartões diferente do valor da Session |
| `payment_amount_below_minimum` | 422 | each payment amount must be at least 100 | Valor de um cartão abaixo de 100 centavos |
| `payment_source_required` | 422 | payment source must contain exactly one vault reference | Cartão sem exatamente uma referência (`cardId` ou `tokenId`) |
| `pan_not_allowed` | 422 | card data must use a vault reference | Dados de cartão em claro |
| `currency_not_brl` | 422 | session currency must be BRL | Session com moeda diferente de `BRL` |
| `invalid_request` | 422 | payment type must be credit and installments must be within the session configuration | `paymentType` diferente de `credit`, ou parcelas menores que 1 ou acima do `installments` da Session |
| `split_seller_not_active` | 422 | This payment could not be completed. Please contact the seller. | Recebedor do split da Session inativo |
| `platform_fee_seller_not_active` | 422 | This payment could not be completed. Please contact the seller. | Recebedor da Session sem as condições exigidas pela taxa da plataforma |

> [!WARNING]
>
> Um `422` com `multiple_payments_limit_reached` também pode chegar depois que a API de Purchases aceitou a Purchase, quando a Session não consegue reservar o pagamento ao mesmo tempo que outra cobrança. Nesse caso a Purchase pode existir e seguir em processamento. Antes de oferecer uma nova tentativa ao comprador, [liste as Purchases](https://docs.malga.io/api-reference/purchases/listar-vendas.md) com o filtro `sessionId` da Session.

## Motivo da recusa por cartão

Quando um cartão é recusado, a Purchase termina `failed` e o cartão traz `status: failed`. O campo `declineReason` traz só o código, sem mensagem, e vem de uma destas origens:

| Origem | Valor de `declineReason` |
| - | - |
| Recusa do emissor ou do provedor | O `declinedCode` da cobrança do cartão, como `insufficient_funds` ou `invalid_cvv`. Os valores estão na [tabela de declinedCode](https://docs.malga.io/documentations/type-tables/declined-code.md) |
| Recusa da API de Charges antes do provedor | O `declined_code` do erro, como `required_cvv` ou `split_multiple_transaction_owners`. Sem código, vem o `type` do erro, como `card_failed`. Veja [Erros da API de Charges](https://docs.malga.io/documentations/welcome/errors-charges.md) |
| Validação da Malga | `merchant_not_owned`, quando o `merchantId` informado não pertence ao seu cliente |

`declineReason` é opcional: quando a Malga não recebe um código, o campo é omitido. Trate um cartão `failed` sem `declineReason`, ou com um código que você não conhece, como recusa genérica. Use o `status` da Purchase e do cartão para saber o desfecho, nunca a ausência de `declineReason`.

Quando o cartão tem `chargeId`, você pode consultar a cobrança em [`GET /v1/charges/{id}`](https://docs.malga.io/api-reference/charges/recuperar-detalhes-de-cobranca) para ver a mensagem e o código original do provedor. Nas recusas da API de Charges antes do provedor e no `merchant_not_owned`, a cobrança não chega a ser criada e o cartão não tem `chargeId`: o motivo disponível é o próprio `declineReason`.

```json theme={null}
{
  "id": "1c6381d1-9fcd-4e9a-a012-93cf0457dcb9",
  "status": "failed",
  "payments": [
    {
      "slotIndex": 1,
      "amount": 5000,
      "status": "failed",
      "chargeId": "7b1e3f0a-2c4d-4e5f-8a9b-0c1d2e3f4a5b",
      "declineReason": "insufficient_funds",
      "refundedAmount": 0
    }
  ]
}
```

## Purchase em revisão

Uma Purchase `pending` com o campo `pendingReview` teve uma anomalia no processamento e não avança sozinha. Interrompa o polling automático e acione o suporte da Malga com o `id` da Purchase.

| `pendingReview.reason` | Descrição |
| - | - |
| `reconciliation_failed` | O prazo de reconciliação terminou sem confirmar o desfecho de uma cobrança |
| `amount_mismatch` | O valor observado na cobrança é diferente do valor esperado para o cartão |
| `claims_exhausted` | O processamento esgotou as tentativas automáticas e o desfecho do valor é desconhecido |

```json theme={null}
{
  "id": "1c6381d1-9fcd-4e9a-a012-93cf0457dcb9",
  "status": "pending",
  "pendingReview": {
    "reason": "reconciliation_failed",
    "since": "2026-07-27T18:05:00Z"
  }
}
```

## Erros por webhook

Os eventos `purchase.failed` e `purchase.void_failed` não trazem o motivo. Ao receber um deles, consulte a Purchase em [`GET /v1/purchases/{id}`](https://docs.malga.io/api-reference/purchases/recuperar-detalhes-de-uma-venda). O passo a passo está em [Erros recebidos por webhook](https://docs.malga.io/documentations/welcome/errors-webhooks.md).

## Exemplos de resposta

> [accordion] 400 · invalid\_request
>
> ```json theme={null}
> {
>   "error": {
>     "type": "bad_request",
>     "code": 400,
>     "message": "Validation error",
>     "businessCode": "invalid_request",
>     "details": []
>   }
> }
> ```

> [accordion] 401 · X-Client-Id ausente
>
> ```json theme={null}
> {
>   "error": {
>     "type": "unauthorized",
>     "code": 401,
>     "message": "Unauthorized",
>     "details": ["unauthorized"]
>   }
> }
> ```

> [accordion] 404 · purchase\_not\_found
>
> ```json theme={null}
> {
>   "error": {
>     "type": "not_found",
>     "code": 404,
>     "message": "Resource not found",
>     "businessCode": "purchase_not_found",
>     "details": ["purchase_not_found"]
>   }
> }
> ```

> [accordion] 408 · Tempo limite excedido
>
> ```json theme={null}
> {
>   "error": {
>     "type": "api_error",
>     "code": 408,
>     "message": "Request timeout",
>     "details": []
>   }
> }
> ```

> [accordion] 409 · idempotency\_key\_payload\_mismatch
>
> ```json theme={null}
> {
>   "error": {
>     "type": "conflict",
>     "code": 409,
>     "message": "Conflict",
>     "businessCode": "idempotency_key_payload_mismatch",
>     "details": ["idempotency_key_payload_mismatch"]
>   }
> }
> ```

> [accordion] 409 · purchase\_operation\_in\_progress
>
> ```json theme={null}
> {
>   "error": {
>     "type": "conflict",
>     "code": 409,
>     "message": "Conflict",
>     "businessCode": "purchase_operation_in_progress",
>     "details": ["purchase_operation_in_progress"]
>   }
> }
> ```

> [accordion] 409 · purchase\_invalid\_state
>
> ```json theme={null}
> {
>   "error": {
>     "type": "conflict",
>     "code": 409,
>     "message": "Conflict",
>     "businessCode": "purchase_invalid_state",
>     "details": ["purchase_invalid_state"]
>   }
> }
> ```

> [accordion] 409 · purchase\_intent\_mismatch
>
> ```json theme={null}
> {
>   "error": {
>     "type": "conflict",
>     "code": 409,
>     "message": "Conflict",
>     "businessCode": "purchase_intent_mismatch",
>     "details": ["purchase_intent_mismatch"]
>   }
> }
> ```

> [accordion] 422 · pan\_not\_allowed
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "pan_not_allowed",
>     "details": ["pan_not_allowed"]
>   }
> }
> ```

> [accordion] 422 · invalid\_request (X-Idempotency-Key ausente)
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "invalid_request",
>     "details": ["invalid_request"]
>   }
> }
> ```

> [accordion] 422 · invalid\_payments\_count
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "invalid_payments_count",
>     "details": ["invalid_payments_count"]
>   }
> }
> ```

> [accordion] 422 · payments\_amount\_mismatch
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "payments_amount_mismatch",
>     "details": ["payments_amount_mismatch"]
>   }
> }
> ```

> [accordion] 422 · payment\_amount\_below\_minimum
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "payment_amount_below_minimum",
>     "details": ["payment_amount_below_minimum"]
>   }
> }
> ```

> [accordion] 422 · currency\_not\_brl
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "currency_not_brl",
>     "details": ["currency_not_brl"]
>   }
> }
> ```

> [accordion] 422 · payment\_source\_required
>
> ```json theme={null}
> {
>   "error": {
>     "type": "validation_error",
>     "code": 422,
>     "message": "Validation error",
>     "businessCode": "payment_source_required",
>     "details": ["payment_source_required"]
>   }
> }
> ```

> [accordion] 503 · Serviço indisponível
>
> ```json theme={null}
> {
>   "error": {
>     "type": "unavailable",
>     "code": 503,
>     "message": "Service unavailable",
>     "details": []
>   }
> }
> ```

> [accordion] Session · 422 purchase\_in\_progress
>
> ```json theme={null}
> {
>   "error": {
>     "type": "bad_request",
>     "code": 422,
>     "message": "purchase is already in progress",
>     "businessCode": "purchase_in_progress",
>     "details": []
>   }
> }
> ```

> [accordion] Session · 422 session\_cannot\_be\_paid
>
> ```json theme={null}
> {
>   "error": {
>     "type": "bad_request",
>     "code": 422,
>     "message": "session cannot be paid in current status",
>     "businessCode": "session_cannot_be_paid",
>     "details": []
>   }
> }
> ```

> [accordion] Session · 404 Session não encontrada
>
> ```json theme={null}
> {
>   "error": {
>     "type": "not_found",
>     "code": 404,
>     "message": "Session not found",
>     "details": []
>   }
> }
> ```


## Related topics

- [Múltiplos cartões](https://docs.malga.io/documentations/payment-methods/multiple-cards.md)
- [Tratamento de erros na integração](https://docs.malga.io/documentations/welcome/errors.md)
- [Erros recebidos por webhook](https://docs.malga.io/documentations/welcome/errors-webhooks.md)
- [Criar uma Venda com múltiplos cartões](https://docs.malga.io/api-reference/purchases/criar-nova-venda.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.