# API-Grundlagen

Adresse, Anmeldung, alle Aufrufe, Rate-Limit und alle Grenzen auf einen Blick.

Diese Seite gilt für alle Aufrufe. Die einzelnen Aufrufe mit ihren Feldern stehen auf den Seiten danach.

## Adresse

```text
https://api.packlets.app
```

Alle Aufrufe laufen über `https://`. Anfragen und Antworten sind JSON in UTF-8.

## Anmeldung

Jeder Aufruf trägt den Schlüssel deines Packlets im Header:

```http
Authorization: Bearer <SAMY_KEY>
Content-Type: application/json
```

Der Schlüssel bestimmt das Packlet und damit den Kanal. Eine Kanal-Angabe im Body gibt es nicht. Ausnahmen sind die Adressen für [Slack](https://packlets.app/docs/slack.md), [Discord](https://packlets.app/docs/discord.md) und [ntfy](https://packlets.app/docs/ntfy.md): Dort steht der Schlüssel in der Adresse, weil diese Tools keinen Header setzen können. Mehr zum Schlüssel steht unter [Schlüssel und Sicherheit](https://packlets.app/docs/sicherheit.md).

## Alle Aufrufe

| Aufruf | Zweck | Kanal-Art |
|---|---|---|
| [`POST /v1/push`](https://packlets.app/docs/api-push.md) | Eine Nachricht schicken. | Kanal, App |
| [`PUT /v1/ui`](https://packlets.app/docs/api-ui.md) | Die Seite einer App setzen. | nur App |
| [`POST /v1/slack/<SAMY_KEY>`](https://packlets.app/docs/slack.md) | Eine Nachricht im Slack-Format schicken. Der Schlüssel steht in der Adresse. | Kanal, App |
| [`POST /v1/discord/<SAMY_KEY>`](https://packlets.app/docs/discord.md) | Eine Nachricht im Discord-Format schicken. Der Schlüssel steht in der Adresse. | Kanal, App |
| [`POST /<SAMY_KEY>`](https://packlets.app/docs/ntfy.md) | Eine Nachricht wie bei ntfy schicken (Text als Body, Angaben in Headern; auch `GET …/publish` und JSON an `/`). | Kanal, App |
| [`POST /v1/session-token/verify`](https://packlets.app/docs/api-seiten.md#token-von-samy-pruefen-lassen) | Ein Session-Token prüfen lassen. Ohne Schlüssel. | nur App |

In die andere Richtung schickt Samy [Webhook-Ereignisse](https://packlets.app/docs/ereignisse.md) an dein Tool.

Mit dem Schlüssel kann dein Tool nur schicken. Nachrichten lesen, ändern oder löschen kann es nicht.

## Anfragen

- Der Body ist JSON und höchstens 64 KiB groß. Größere Anfragen lehnt Samy mit `413` ab.
- Felder, die Samy nicht kennt, werden ignoriert.
- Leere Texte (`""`) und `null` bei optionalen Feldern zählen als nicht angegeben.
- `POST /v1/push` nimmt auch Formulardaten an. Für einen schnellen Test reicht also `curl -d text=Hallo`.
- Aus einer Webseite im Browser lässt sich die API nicht direkt rufen (kein CORS). Ruf sie von deinem Server aus.

## Antworten

Erfolg ist immer Status `200` mit JSON. Jeder Fehler hat eine feste Kennung im Feld `error`:

```json
{
  "error": "invalid_body",
  "message": "Ungültige Daten.",
  "details": [{ "path": "text", "message": "text darf nicht leer sein" }]
}
```

Alle Kennungen stehen unter [Fehlercodes](https://packlets.app/docs/fehler.md).

## Rate-Limit

Erlaubt sind **60 Aufrufe pro Minute** und Packlet, für jeden Aufruf einzeln gezählt. Ein neuer Schlüssel für dasselbe Packlet zählt weiter. Aufrufe ohne gültigen Schlüssel zählen pro IP-Adresse. Dazu gilt ein Limit pro Konto: **300 Aufrufe pro Minute** über alle deine Packlets zusammen. Beide Limits sind reiner Missbrauchsschutz.

Jede Antwort nennt den Stand in diesen Headern:

| Header | Inhalt |
|---|---|
| `x-ratelimit-limit` | Erlaubte Aufrufe pro Minute. |
| `x-ratelimit-remaining` | Wie viele in dieser Minute noch übrig sind. |
| `x-ratelimit-reset` | Sekunden, bis die Zählung neu beginnt. |
| `retry-after` | Nur bei `429`: so viele Sekunden warten. |

## Grenzen

| Was | Grenze |
|---|---|
| Anfrage | 64 KiB |
| `text` einer Nachricht | 1 bis 10.000 Zeichen |
| `title` einer Nachricht | 80 Zeichen |
| `url`, `image`, `page` | 2.048 Zeichen |
| Knöpfe pro Nachricht | 3 |
| Elemente pro Nachricht | 12 |
| `id` eines Elements | 1 bis 40 Zeichen: Buchstaben, Ziffern, `_`, `-` |
| `id` eines Knopfs | 1 bis 64 Zeichen |
| Deine Nachricht in einem Kanal mit Antworten | 4.000 Zeichen |
| Aufrufe | 60 pro Minute und Packlet, 300 pro Minute und Konto |
| Packlets pro Konto | 100 |
| Aufbewahrung | Nachrichten 365 Tage, Protokoll 30 Tage |

Die Grenzen der einzelnen Elemente stehen unter [Elemente](https://packlets.app/docs/elemente.md).
