# Order Notifications

To receive order notifications. Configure a callback URL either per-order through <mark style="color:$danger;">**`responseUrl`**</mark>  or at the merchant level via the [Swapped Dashboard](https://dashboard.swapped.com/developers).

### Callback URL Priority

1. <mark style="color:$danger;">**`responseUrl`**</mark> in the iframe URL (if provided)
2. Merchant-level webhook in Dashboard (if configured)
3. No callback (if neither is set)

> **Important:** The callback destination is locked at order creation and cannot be changed afterwards.

{% hint style="warning" %}
Callbacks may be resent due to network errors. \
\ <mark style="color:$danger;">**Always verify an order hasn't already been credited before processing.**</mark> \
\
[See Order Notification Retry Policy for retry behavior.](/misc/order-notification-retry-policy.md)
{% endhint %}

### Verifying Signatures

Validate callbacks using the <mark style="color:$danger;">**`signature`**</mark> header. Compute an HMAC-SHA256 using your secret key and the raw request body, then compare.

**Example with NodeJS:**

{% code overflow="wrap" %}

```javascript
import crypto from 'crypto';

const secretKey = 'sk_test_key'; // Replace with your secret key
const requestBody = '{ "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c"}'

const signature =
  crypto
    .createHmac('sha256', secretKey)
    .update(requestBody)
    .digest('base64'); 
```

{% endcode %}

Both <mark style="color:$danger;">**`order_broadcasted`**</mark> and <mark style="color:$danger;">**`order_cancelled`**</mark> are final states. An order cannot transition from completed to cancelled.

### Callback Payloads

#### `payment_pending`

Order created, awaiting customer payment.

```json
{
  "order_id": "9af6cd02-174f-438f-a362-fc6545ad125b",
  "external_transaction_id": null,
  "external_customer_id": null,
  "order_status": "payment_pending",
  "order_crypto": "LTC",
  "order_type": "buy",
  "order_crypto_amount": "0.070175135286017",
  "order_crypto_address": "ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah",
  "order_crypto_tag": null,
  "order_amount_usd": 8.18,
  "order_amount_usd_plus_fees": 8.9,
  "order_amount_eur": 7.01,
  "order_amount_eur_plus_fees": 7.62,
  "network": "litecoin"
}
```

#### `order_completed`

Payment successful, crypto purchase processed.

```json
{
  "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c",
  "order_crypto_amount": 0.070175135286017,
  "order_crypto": "LTC",
  "order_status": "order_completed",
  "order_crypto_address": "ltc1qlec2yfpkdvn4lr0vpf27qggrxtu34zeu5l6g2u",
  "external_customer_id": "1234567",
  "order_amount_usd": "25",
  "order_amount_usd_plus_fees": "25.5",
  "order_amount_eur": "21",
  "order_crypto_tag": 12345,
  "order_amount_eur_plus_fees": "22.5",
  "network": "litecoin"
}
```

#### `order_broadcasted`

Transaction broadcast to blockchain.

```json
{
  "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c",
  "order_crypto_amount": 0.070309096973144,
  "order_crypto": "LTC",
  "order_status": "order_broadcasted",
  "transaction_id": "ea458dda0ff8583199bdd4d9b9a69a2813694764a633fd40b27de22a868cebec",
  "order_crypto_address": "ltc1qlec2yfpkdvn4lr0vpf27qggrxtu34zeu5l6g2u",
  "external_customer_id": "1234567",
  "order_amount_usd": "25",
  "order_amount_usd_plus_fees": "25.5",
  "order_amount_eur": "21",
  "order_crypto_tag": 12345,
  "order_amount_eur_plus_fees": "22.5",
  "network": "litecoin"
}
```

#### `order_cancelled`

Order cancelled (payment failure, user cancellation, etc.).

```json
{
  "order_id": "9ab49879-92f0-44fc-992e-460285c879e8",
  "order_status": "order_cancelled",
  "order_type": "buy",
  "order_crypto": "LTC",
  "external_transaction_id": null,
  "external_customer_id": null
}
```

### Response Fields

| Field                                                                | Description                                           |
| -------------------------------------------------------------------- | ----------------------------------------------------- |
| <mark style="color:$danger;">**`order_id`**</mark>                   | Swapped order ID                                      |
| <mark style="color:$danger;">**`order_status`**</mark>               | Current order state                                   |
| <mark style="color:$danger;">**`order_crypto`**</mark>               | Cryptocurrency code                                   |
| <mark style="color:$danger;">**`order_crypto_amount`**</mark>        | Crypto amount received                                |
| <mark style="color:$danger;">**`order_crypto_address`**</mark>       | Destination wallet address                            |
| <mark style="color:$danger;">**`order_crypto_tag`**</mark>           | Destination tag/memo (XRP, TON, etc.)                 |
| <mark style="color:$danger;">**`network`**</mark>                    | Blockchain network used                               |
| <mark style="color:$danger;">**`order_amount_usd`**</mark>           | Crypto value in USD (mid-market rate, excludes fees)  |
| <mark style="color:$danger;">**`order_amount_usd_plus_fees`**</mark> | USD amount including platform fee                     |
| <mark style="color:$danger;">**`order_amount_eur`**</mark>           | Crypto value in EUR                                   |
| <mark style="color:$danger;">**`order_amount_eur_plus_fees`**</mark> | EUR amount including platform fee                     |
| <mark style="color:$danger;">**`transaction_id`**</mark>             | Blockchain transaction hash (broadcasted orders only) |
| <mark style="color:$danger;">**`external_customer_id`**</mark>       | Your customer ID (if provided in URL)                 |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.swapped.com/swapped-ramp/readme/order-notifications.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
