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

# API Guide

> REST integration for B2B partners — products, orders, wallet, and webhooks under /api/v1/business.

# API Guide

Integrate directly with UGiftMe using **`https://api-stage.ugift.me/api/v1/business`** (sandbox) or **`https://api.ugift.me/api/v1/business`** (production).

## Authentication

Send your integration API key on every request:

`X-API-Key: <your-api-key>`

Keys are issued from the **dashboard**. If an IP whitelist is configured on the key, calls must originate from an allowed address.

## Verify Credentials

`GET /api/v1/business/auth` returns minimal integration metadata when `X-API-Key` is valid. Use it for health checks and connection tests.

## Orders and async behaviour

When **async order processing** is enabled, **`POST /api/v1/business/orders`** responds with **`202 Accepted`** and a body such as:

```json theme={null}
{ "orderRequestId": "<id>", "status": "queued" }
```

Poll **`GET /api/v1/business/orders/order-requests/{orderRequestId}`** for status, result, and errors. Successful synchronous creation may still return **`201 Created`** when async mode is off.

Optional **`Idempotency-Key`** (header) is supported for `POST /orders` and `POST /orders/bulk`; reusing the same key with a different payload returns **`400`**.

Responses may include **`X-Business-Orders-Async`** (`true` / `false`) for diagnostics.

## Error responses

Business API failures return JSON with at least an **`error`** string. There is no global `success` / `action` / `code` / `timestamp` envelope.

| Status  | Typical body                                                                                    |
| ------- | ----------------------------------------------------------------------------------------------- |
| **400** | `{ "error": "...", "message": "..." }` — optional `validEvents` on webhook validation           |
| **401** | `{ "error": "Missing API key" }` or `{ "error": "Invalid API key", "reason": "..." }`           |
| **402** | `{ "error": "Insufficient funds", "required", "available", "currency" }` on order create        |
| **403** | `{ "error": "..." }` — IP allow list, incomplete business on `/auth`, or resource access denied |
| **404** | `{ "error": "..." }` — optional `message` when access is denied                                 |
| **429** | `{ "error": "Too many ..." }` plus standard rate-limit headers                                  |
| **500** | `{ "error": "..." }` — optional `message` or `details`                                          |

See the **UGiftMe API Reference** tab for endpoint-specific examples.

## Webhooks (B2B)

Webhooks are **outbound only**: UGiftMe **POSTs** JSON to your HTTPS URL when something happens. Your server **receives** those requests; you do not send webhook payloads back on that URL.

What you manage via the API is the **subscription** (stored URL, event types, active flag). Use these endpoints with **`X-API-Key`**:

| Method     | Path                             | Purpose                                                                                                         |
| ---------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| **POST**   | `/api/v1/business/webhooks`      | Register a URL and event types. Response includes a **secret** once — store it to verify `X-Webhook-Signature`. |
| **GET**    | `/api/v1/business/webhooks`      | List your subscriptions (secrets are never returned).                                                           |
| **PATCH**  | `/api/v1/business/webhooks/{id}` | Update `url`, `events`, `description`, or `isActive` **without** a new secret (prefer over delete + recreate).  |
| **DELETE** | `/api/v1/business/webhooks/{id}` | Remove a subscription.                                                                                          |

**PATCH** accepts any combination of `url`, `events`, `description`, and `isActive`, but at least one field is required. Set `isActive` to `false` to pause deliveries without deleting the webhook. When updating `events`, send a **non-empty** array of allowed types.

### Allowed `events`

* **Orders:** `order.queued`, `order.processing`, `order.succeeded`, `order.failed`
* **Catalog / wallet:** `product.updated`, `wallet.updated`

Business API integrations are wallet-funded (no Stripe/Mollie on `/business`). Use **`wallet.updated`** when balance changes and **`order.*`** for fulfillment lifecycle.

### Example: update a subscription

```http theme={null}
PATCH /api/v1/business/webhooks/65d3f4a5b6c7d89012345678
X-API-Key: <your-api-key>
Content-Type: application/json

{
  "url": "https://hooks.example.com/ugiftme/v2",
  "events": ["order.succeeded", "wallet.updated"],
  "isActive": true
}
```

```json theme={null}
{
  "message": "Webhook updated successfully",
  "webhook": {
    "_id": "65d3f4a5b6c7d89012345678",
    "url": "https://hooks.example.com/ugiftme/v2",
    "events": ["order.succeeded", "wallet.updated"],
    "isActive": true
  }
}
```

For **outbound deliveries** (what UGiftMe POSTs to your URL), headers, signature verification, retries, and per-event payload examples, see **[Webhook deliveries](/docs/webhook-deliveries)**.

## Related docs

* **[Webhook deliveries](/docs/webhook-deliveries)** — receive events, verify `X-Webhook-Signature`, test with `/webhooks/test`

* **Interactive OpenAPI:** use the **UGiftMe API Reference** tab (generated routes under **`/api-reference/`**, for example **`/api-reference/authentication/verify-credentials`**).
