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

# First request

> From zero to an alert sent through the API, in five calls.

This guide takes your system from a freshly created key to a sent and confirmed alert. You need a token (see [Authentication](https://docs.needalert.app/en/api/authentication.md)) and a unit with at least one subscriber, so the alert reaches someone.

In the examples, `$API` is the API address and `$TOKEN` the key's token:

```bash theme={null}
export API=https://needalert.app/api/v1
export TOKEN='3|na_...'
```

**1. Discover the key's units**

```bash theme={null}
curl "$API/establishments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
```

The response lists only the units the key reaches, with its permissions in each one (abridged):

```json theme={null}
{
  "data": [
    {
      "id": 12,
      "tenant_id": 7,
      "name": "Bom Pão — Downtown",
      "slug": "bom-pao-downtown",
      "status": "active",
      "permissions": ["view", "create_items", "edit_items", "dispatch_events"]
    }
  ]
}
```

Keep the unit `id` (`12`) and the chain `tenant_id` (`7`).

**2. Find the item by your reference**

Look the item up by your own system's code, in `external_reference` (exact match):

```bash theme={null}
curl "$API/establishments/12/items?external_reference=SKU-123" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
```

If `data` comes back empty, create the item. `translations` carries the block of the chain's default language (`pt_BR` or `en`), with `name` required:

```bash theme={null}
curl -X POST "$API/establishments/12/items" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 5c1b2a9e-6f0d-4c3e-9a7b-1d2e3f4a5b6c" \
  -d '{
    "queue_type": "single",
    "external_reference": "SKU-123",
    "translations": {
      "en": { "name": "Cheese bread", "description": "Fresh from the oven" }
    }
  }'
```

`queue_type` sets the alert type: `single` for a **one-time alert** (the subscription ends after the first alert) or `recurring` for a **recurring alert** (the subscription stays and receives every alert). The **201** response carries the item (abridged):

```json theme={null}
{
  "data": {
    "id": 42,
    "establishment_id": 12,
    "public_code": "K7Q2M",
    "external_reference": "SKU-123",
    "name": "Cheese bread",
    "queue_type": "single",
    "status": "active",
    "subscribers_count": 0
  }
}
```

**3. Estimate the cost**

```bash theme={null}
curl "$API/establishments/12/items/42/dispatch-preview" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
```

```json theme={null}
{
  "data": {
    "recipients_count": 38,
    "credits_cost": 38,
    "current_balance": 950,
    "sufficient": true,
    "schedule": {
      "min_lead_minutes": 10,
      "max_lead_days": 90,
      "warning_lead_minutes": 120
    }
  }
}
```

One credit per person notified. If `sufficient` is `false`, the dispatch would be refused with `insufficient_credits`.

**4. Send the alert**

```bash theme={null}
curl -X POST "$API/establishments/12/items/42/events" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9f8e7d6c-5b4a-4c3d-8e2f-1a0b9c8d7e6f" \
  -d '{ "message": "Warm cheese bread coming out right now!" }'
```

`message` takes up to 200 characters; `title` (up to 120) is optional. To schedule, add `scheduled_at` in ISO 8601 UTC, within the `schedule` window from the previous step. Always send a new `Idempotency-Key` per intended dispatch: if the connection drops and you repeat the call with the same key, the alert doesn't go out twice (see [Idempotency](https://docs.needalert.app/en/api/idempotency.md)).

The **201** response carries the dispatch as `pending` (or `scheduled`, if scheduled; `dispatched` when nobody was subscribed):

```json theme={null}
{
  "data": {
    "id": 9001,
    "item": { "id": 42, "public_code": "K7Q2M", "name": "Cheese bread" },
    "message": "Warm cheese bread coming out right now!",
    "status": "pending",
    "recipients_count": 38,
    "credits_cost": 38,
    "created_by": null,
    "created_by_api_client": { "id": 3, "name": "Downtown store ERP" }
  }
}
```

**5. Follow the result**

Sending happens in the background. Poll the dispatch until `status` leaves `pending` or `processing`:

```bash theme={null}
curl "$API/establishments/12/events/9001" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
```

`dispatched`: sent; `sent_count` and `failed_count` detail the deliveries and the credits were debited. `failed`: not sent; `failure_reason` says why (for example, `insufficient_credits` at send time). `scheduled`: waiting for `scheduled_at`; it can be rescheduled (`PATCH`) or cancelled (`DELETE`).

## If the dispatch is refused

A dispatch may be refused right away, with **422** and a `code`:

| `code` | Cause | What to do |
| - | - | - |
| `insufficient_credits` | `errors.required` credits needed, `errors.available` available. | Buy credits in the dashboard and retry with a new `Idempotency-Key`. |
| `item_not_dispatchable` | The item isn't active, or the unit or the chain isn't active. | Check the item's and the unit's `status`. |
| `dispatch_in_progress` | A dispatch for this item is already in progress. | Wait and poll the dispatch in progress. |
| `dispatch_too_soon` | The item was dispatched moments ago. | Wait a few seconds and use a new `Idempotency-Key`. |
| `schedule_slot_taken` | There's already a scheduled dispatch for this item in the same minute. | Pick another time. |

The full list of codes is in [Conventions](https://docs.needalert.app/en/api/conventions.md); every endpoint is detailed in the **Endpoints** group of this tab.


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