# Limits and rate limits

## Rate limit

Each key may send **120 requests per minute**. Requests are counted in fixed 60-second windows. Every response carries the current state in headers following the IETF draft for RateLimit headers:

```
RateLimit-Policy: "default";q=120;w=60
RateLimit: "default";r=87;t=34
```

| Value | Meaning |
|---|---|
| `q` | Requests per window |
| `w` | Window size in seconds |
| `r` | Requests left in the current window |
| `t` | Seconds until the next window |

When the limit is reached the API answers `429` [`rate_limited`](https://docs.kalender-sync.de/en/api/errors/rate_limited/) with a `Retry-After` header (seconds). Wait that long, then retry.

There is also a generous ceiling **per IP address** (600 requests per minute), so several websites on shared hosting don't slow each other down.

**Tips:**

- Use [batch](https://docs.kalender-sync.de/en/api/batch/) for many events: 100 operations count as one request.
- Send changes when they happen instead of sending everything regularly. For a complete reconciliation there is the [full sync](https://docs.kalender-sync.de/en/api/full-sync/).
- The API recognizes unchanged events itself (`changed: false`); you don't need to track that.

## Limits by plan

| | Sandbox (any plan) | Basic | Professional |
|---|---|---|---|
| Calendars | 3 sandbox calendars | 1 live calendar | 10 live calendars |
| Events per calendar | 500 | 5,000 | 5,000 |
| Active subscribers (account) | | 500 | 5,000 |

A series counts as one event. More on request. What happens when you reach a limit: [Plans and limits](https://docs.kalender-sync.de/en/abo-kalender/tarife/#what-happens-when-you-reach-a-limit).

## Technical limits

| | Limit |
|---|---|
| Active keys per account | 10 |
| JSON body | 1 MB |
| Batch | 100 operations |
| Logo / banner | 512 KB / 2 MB |
| Calendar name | 100 characters |
| Calendar description | 1,000 characters |
| `external_id` | 1 to 128 characters: `A-Z a-z 0-9 . _ : -` |
| Event title | 255 characters |
| Event description | 65,536 characters input, up to 8,000 characters of text stored |
| Location | 500 characters |
| URLs | 2,000 characters, `https://` only |
| `categories` | 10 entries of 50 characters |
| `metadata` | 2 KB of JSON |
| `recurrence.rules` | 5 rules of 500 characters |
| `recurrence.except_dates` | 1,000 |
| `recurrence.overrides` | 500 |
| `COUNT`, `INTERVAL` | 1 to 1,000 |
| `default_duration` | up to `PT24H` |
| Page size when listing | 100 |
| Lifetime of a full sync | 1 hour |
| `Idempotency-Key` | 255 characters, kept for 24 hours |