# Send counts with the API

- **Batch.** One request carries up to 10,000 points (2 MB) for any number of watches. Each request counts once against the plan, however many points it holds: batch, do not send one request per event.
- **The 5-minute rule.** CountWatch counts in 5-minute buckets and judges only windows with no missing bucket. A watch the API creates is an **explicit source**: a bucket without a point is missing data, not zero. So either send a point for **every 5-minute bucket, zeros included** (a count query or a counter flushed per bucket; the no-data alert then works), or, if you send one point per event, send the request with `"source": "push"`: the watches it creates read a bucket without points as zero. Never send one point per hour: an hourly total in one bucket looks like one huge event.
- **`add` or `set`.** `add` adds to the 5-minute bucket; `set` replaces the bucket total (for counters you already sum).
- **Time.** Without `ts`, the arrival time counts. Unix time is in **milliseconds**: seconds are refused with `ts_unit`.
- **Retries.** Send an `Idempotency-Key` with every batch: a retry within 24 hours returns the first result and adds nothing. A point `id` does the same for single points.
- **When a request is refused.**
  - `429 rate_limited` with `Retry-After`: too many requests a second; send bigger batches.
  - `429 request_limit_reached`: the month's requests are used up (Free only). It lifts when the month ends or the plan changes.
  - A point refused with `watch_limit_reached` says so in its `detail`.
  - `503`: busy for a moment; retry after `Retry-After`.
- **No recipe for your source?** See "No recipe for your source" ([general methods](/docs/methods)).
- **No code?** Make a metric's **webhook URL** in the dashboard and paste it into any tool that sends webhooks: each hit adds 1 (or `?n=`) to the watch named by the query string, for example `…/v1/hit/<secret>?shop=eu`. With an admin key, `POST /v1/metrics/{metric}/ping-link/rotate` makes or replaces it.
