# curl examples

Every example assumes:

```bash
export NOTICEFOX_URL=https://api.noticefox.app
export NOTICEFOX_TOKEN=nfx_send_…   # a send token
```

## The JSON endpoint: `POST /v1/notifications`

The canonical endpoint. The token goes in the `Authorization` header and the fields in a
JSON body (`Content-Type: application/json`).

A plain message:

```bash
curl "$NOTICEFOX_URL/v1/notifications" \
  -H "Authorization: Bearer $NOTICEFOX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"message": "Deploy finished"}'
```

An animated scene with its parameters, a link, a time-sensitive level and a tag (a newer
send with the same tag replaces the older notification on the devices it reaches):

```bash
curl "$NOTICEFOX_URL/v1/notifications" \
  -H "Authorization: Bearer $NOTICEFOX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Garage",
    "message": "Door opened",
    "scene": "garage",
    "scene_params": {"doorState": "open"},
    "bell_color": "red",
    "url": "https://ha.example.net/garage",
    "url_title": "View Garage",
    "level": "time-sensitive",
    "group": "home",
    "tag": "garage-door",
    "ttl": 3600
  }'
```

Pushover priorities work as levels (`-2` to `2`), and a retry-safe send carries an
`Idempotency-Key`: a retry with the same key and the byte-identical request returns the
original response instead of sending twice.

```bash
curl "$NOTICEFOX_URL/v1/notifications" \
  -H "Authorization: Bearer $NOTICEFOX_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: build-4711-finished' \
  -d '{"title": "CI", "message": "Build 4711 failed", "level": 1, "scene": "fireworks", "scene_params": {"bursts": 3}}'
```

Only to the Watch:

```bash
curl "$NOTICEFOX_URL/v1/notifications" \
  -H "Authorization: Bearer $NOTICEFOX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"message": "Stand up", "target": "watch", "level": "passive"}'
```

## The simple endpoint: `GET|POST /v1/send/{send_key}`

The token is in the path, so a URL is all a tool needs. The fields can come from the query
string, a form body, a JSON body, a raw text body (which becomes the message), and the
`X-Title` and `X-Level` headers.

A raw text body. curl labels `-d` bodies as forms, and a form body with no `=` is taken as
the message, exactly as sent:

```bash
curl -d "Build finished" "$NOTICEFOX_URL/v1/send/$NOTICEFOX_TOKEN"
```

Query parameters. A GET without a message is refused, so a preview of a bare token URL
sends nothing. A URL like this one **does** carry a message, so it notifies every time
anything fetches it, link previews and preloaders included; don't paste it into chats or
documents:

```bash
curl "$NOTICEFOX_URL/v1/send/$NOTICEFOX_TOKEN?title=Backup&message=Done&level=passive"
```

Scene parameters are `param.<name>=<value>`:

```bash
curl "$NOTICEFOX_URL/v1/send/$NOTICEFOX_TOKEN?message=Door+opened&scene=garage&param.doorState=open"
```

A message that contains `=` must be form-encoded, or sent as `text/plain`:

```bash
curl --data-urlencode "message=CPU=97%" "$NOTICEFOX_URL/v1/send/$NOTICEFOX_TOKEN"
```

```bash
curl -H 'Content-Type: text/plain' -d "x=1 failed" "$NOTICEFOX_URL/v1/send/$NOTICEFOX_TOKEN"
```

ntfy-style headers, with the message as the body:

```bash
curl -H 'X-Title: Disk' -H 'X-Level: time-sensitive' -d "Disk 91% full" "$NOTICEFOX_URL/v1/send/$NOTICEFOX_TOKEN"
```

The sources merge by precedence (JSON body, then form body, then query, then headers), and
then a message is required. The same field given in two places with different values is
`400 conflicting_field`. See [Fields](fields.md#aliases-precedence-and-conflicts).

## Other calls a send token may make

The status of a message the token sent. Keep the `id` of the 202 when you send (here with
`jq`), then ask for it:

```bash
MESSAGE_ID=$(curl -s "$NOTICEFOX_URL/v1/notifications" \
  -H "Authorization: Bearer $NOTICEFOX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"message": "Nightly backup finished"}' | jq -r .id)

curl "$NOTICEFOX_URL/v1/notifications/$MESSAGE_ID/status" \
  -H "Authorization: Bearer $NOTICEFOX_TOKEN"
```

The scene catalog, with each scene's parameters:

```bash
curl "$NOTICEFOX_URL/v1/scenes" -H "Authorization: Bearer $NOTICEFOX_TOKEN"
```

The names and platforms of the account's devices, for choosing a `target`:

```bash
curl "$NOTICEFOX_URL/v1/devices" -H "Authorization: Bearer $NOTICEFOX_TOKEN"
```

## Responses

A 202 means the notification is stored and queued:

```json
{ "id": "ntf_01JABCDEFGHJKMNPQRSTVWXYZ0", "status": "accepted", "request_id": "req_8hT2kLm4Qw9Zx1Cv3Bn5" }
```

Every error has the same shape. `field` names the offending field when there is one:

```json
{
  "error": { "code": "invalid_scene_param", "message": "doorState must be one of open, closed, opening, closing.", "field": "scene_params.doorState" },
  "request_id": "req_8hT2kLm4Qw9Zx1Cv3Bn5"
}
```

Every send response after the token is known carries `X-RateLimit-Limit`,
`X-RateLimit-Remaining` and `X-RateLimit-Reset`. See [Errors](errors.md) and
[Quotas](quotas.md).
