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

# Order creation

> The notice that a payment order was created or that its creation failed.

> [!NOTE]
>
> **Coming soon.** This webhook is not available yet.

TapiPay notifies you with this webhook when a [payment order](https://devs.tapipay.la/en/resources/payment-orders.md) is created or when the creation of the charge fails. It only comes with three `POST /v2/debts/orders` responses: `201`, `422 ORDER_NOT_CREATED` and `500`. With any other one (for example, an invalid field, a contact that does not exist or a key already used), there is no webhook: the reason only reaches you in the response.

On a `500`, this webhook may or may not arrive. If `ORDER_CREATION_FAILED` arrives with `PROVIDER_UNAVAILABLE`, it does not mean nothing was charged: retry with the same `externalRequestId`, as described in [Retries and idempotency](https://devs.tapipay.la/en/resources/payment-orders.md#retries-and-idempotency).

| `type` | `orderStatus` | When it arrives |
| - | - | - |
| `ORDER_CREATION_SUCCESS` | `PROCESSING` | The order was created. |
| `ORDER_CREATION_FAILED` | `FAILED` | The order creation failed. The reason comes in `creationError`. |

> [!NOTE]
>
> It is part of the [order and payment method webhooks](https://devs.tapipay.la/en/webhooks.md#orders-and-payment-methods): it shares the endpoint, the security and the contract with them. Its idempotency key is `id`.

## Creation and charge are separate notices

`ORDER_CREATION_SUCCESS` reports that the order **was created**, not that it was charged. The result of the charge reaches you later, with the [order payment](https://devs.tapipay.la/en/webhooks/order-payment.md).

You can receive `ORDER_CREATION_FAILED` and then `ORDER_PAYMENT_CONFIRMED` for the same order, if the bank ended up processing the charge. In that case, take the charge as final: the money came in.

## The payload

| Field | Type | Present | Description |
| - | - | - | - |
| `type` | String | Always | `ORDER_CREATION_SUCCESS` or `ORDER_CREATION_FAILED`. Use it to route. |
| `hash` | String \| null | Always | Verification hash. `null` if you do not have a public key configured. See [Webhook security](https://devs.tapipay.la/en/webhooks/security.md#encrypted-hash). |
| `id` | String (uuid) | Always | Unique identifier of the notification. If it reaches you again, it carries the same `id`. **Use it as the idempotency key.** |
| `orderId` | String (uuid) | Variable | The order's `orderId`. Always in `ORDER_CREATION_SUCCESS`. In `ORDER_CREATION_FAILED` only if the order got to be created. |
| `externalOrderId` | String | Always | Your identifier for the order, the `externalRequestId`. |
| `orderStatus` | String | Always | `PROCESSING` in `ORDER_CREATION_SUCCESS`, `FAILED` in `ORDER_CREATION_FAILED`. |
| `companyCode` | String | Always | Code of the order's company. |
| `externalClientId` | String | Always | Your identifier for the user. |
| `amount` | Number | Always | Order amount, in pesos with up to 2 decimals. |
| `currency` | String | Always | Currency, in ISO 4217. For now `MXN`. |
| `paymentProcessor` | String | Always | For now `BANK_ACCOUNT`. |
| `paymentMethod` | Object | Variable | The order's payment method: `{ type, externalPaymentMethodId }`. Always in `ORDER_CREATION_SUCCESS`. In `ORDER_CREATION_FAILED` it may not come, for example with `PAYMENT_METHOD_NOT_SUPPORTED`. It never carries the account number or the CLABE. |
| `creationError` | Object | Only `ORDER_CREATION_FAILED` | Reason: `{ code, message }`. See [Reasons](#reasons). |
| `additionalData` | Object | Always | For now it always arrives empty (`{}`). |
| `createdAt` | String | Only `ORDER_CREATION_SUCCESS` | When the order was created, in ISO 8601 UTC. |
| `failedAt` | String | Only `ORDER_CREATION_FAILED` | When the creation failed, in ISO 8601 UTC. |

> [!WARNING]
>
> **If `orderId` or `paymentMethod` do not come, the key is not there: they do not arrive as `null` or empty.** Check that they exist before reading them.

## Reasons

`creationError.code` is a TapiPay code, not the bank's. `message` comes in English and is meant for your logs, not for showing to the user.

| `code` | `message` | What it means |
| - | - | - |
| `PAYMENT_METHOD_REQUIRED` | The order requires a payment method | The order needs a payment method. |
| `PAYMENT_METHOD_NOT_SUPPORTED` | The payment method is not supported for this order | The payment method cannot be used for this kind of order. |
| `PAYMENT_METHOD_INACTIVE` | The payment method is not active | The bank reported that the account is not active. Ask the user to register another one. |
| `ORDER_REJECTED` | The order was rejected by the payment provider | The bank declined the charge. |
| `PROVIDER_UNAVAILABLE` | The payment provider could not confirm the order | The bank did not confirm in time. The order can still be charged. |
| `INTERNAL_ERROR` | The order could not be created | A TapiPay failure, not attributable to your request. |
| `INVALID_ORDER_REQUEST` | The order request was rejected | The order does not meet a rule. It was not created. |

> [!NOTE]
>
> Treat the list of codes as **open**: new codes can be added. If you receive one you do not know, treat it as a creation failure with no specific action.

## Examples

An order that is created, one that is created but fails, and one whose creation failed before the order existed (without `orderId`). The examples correspond to an integration without a public key, which is why `hash` comes as `null`.

```json Created theme={null}
{
  "type": "ORDER_CREATION_SUCCESS",
  "hash": null,
  "id": "3c9e7a14-6b2d-5f80-a1c3-9d4e8b2f6a07",
  "orderId": "6f1c2b9e-4d3a-4b8e-9a71-2c5d8e0f1a23",
  "externalOrderId": "CARGO-2026-00042",
  "orderStatus": "PROCESSING",
  "companyCode": "MX-S-12345",
  "externalClientId": "CLI-00042",
  "amount": 350.00,
  "currency": "MXN",
  "paymentProcessor": "BANK_ACCOUNT",
  "paymentMethod": { "type": "BANK_ACCOUNT", "externalPaymentMethodId": "b7e4a0c2-9f13-4e6d-8a25-71c3d9e0b4f8" },
  "additionalData": {},
  "createdAt": "2026-10-23T15:00:04.000Z"
}
```

```json Inactive account theme={null}
{
  "type": "ORDER_CREATION_FAILED",
  "hash": null,
  "id": "d17b4e92-0a6c-5e31-8f2b-6c3a9e1d7b40",
  "orderId": "4e7b1a90-2c6d-4f3e-8a15-6b9d0c2e7f48",
  "externalOrderId": "CARGO-2026-00043",
  "orderStatus": "FAILED",
  "companyCode": "MX-S-12345",
  "externalClientId": "CLI-00043",
  "amount": 980.00,
  "currency": "MXN",
  "paymentProcessor": "BANK_ACCOUNT",
  "paymentMethod": { "type": "BANK_ACCOUNT", "externalPaymentMethodId": "7d2c9e14-5a3b-4f86-b1e0-9c4a8f6d2b53" },
  "creationError": { "code": "PAYMENT_METHOD_INACTIVE", "message": "The payment method is not active" },
  "additionalData": {},
  "failedAt": "2026-10-23T15:05:12.000Z"
}
```

```json Without order theme={null}
{
  "type": "ORDER_CREATION_FAILED",
  "hash": null,
  "id": "8a5f2c63-e91d-5b47-9c06-1f8d3a7e4b29",
  "externalOrderId": "CARGO-2026-00044",
  "orderStatus": "FAILED",
  "companyCode": "MX-S-12345",
  "externalClientId": "CLI-00044",
  "amount": 120.00,
  "currency": "MXN",
  "paymentProcessor": "BANK_ACCOUNT",
  "paymentMethod": { "type": "BANK_ACCOUNT", "externalPaymentMethodId": "3f8a6d21-7c4e-4b95-a0d2-5e9b1c7f4a36" },
  "creationError": { "code": "INVALID_ORDER_REQUEST", "message": "The order request was rejected" },
  "additionalData": {},
  "failedAt": "2026-10-23T15:07:30.000Z"
}
```

## Recommendations

* **Process each notification only once.** The same notification can arrive more than once, always with the same `id`. Store the processed `id` values in persistent storage.
* **Correlate by `externalOrderId`.** It is the only identifier that always comes: `orderId` is missing if the order did not get to be created.
* **Do not assume an arrival order** between this notice and the [order payment](https://devs.tapipay.la/en/webhooks/order-payment.md) ones.
* **Ignore fields you do not know**: new fields can be added.


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