# Change Feed

Tell me when this company changes. Watch lists, a change feed and signed webhooks.

A daily read of each watched company across Companies House, sanctions, payment practices, contracts and the sponsor register; every change an event, by webhook (signed) and by pull. People counted, never named.

Every other endpoint answers a question once. This one keeps asking. Put a company on your watch list and it's read every day from the public record we already hold: Companies House (status, filings due and overdue, directors and PSCs counted, ID verification), distress signals, the UK Sanctions List, its payment practices reports, public contracts won, and the register of licensed visa sponsors. Every change is an event with a plain sentence, posted to your webhook (signed) and kept in a feed you can pull. Nobody is named: people are counted, so an event can go anywhere. Two credits per company per calendar month; reading your watches, events and webhook is free.

- Price: 2 credits per company per month
- Page: https://meetkatalis.com/apis/change-feed
- OpenAPI: https://meetkatalis.com/openapi.yaml

## Endpoints

- `POST /api/v1/watch` — Body: { "company": "01234567", "label": "optional" } — 2 credits now, then 2 a month
- `GET /api/v1/watch` — Your watches with the last state seen (free)
- `DELETE /api/v1/watch?company=…` — Stop watching
- `GET /api/v1/watch/events?since=…` — The event feed, oldest first after 'since' (free)
- `PUT /api/v1/watch/webhook` — Body: { "url": "https://…" } — the signing secret comes back once

## Call it

```bash
curl -X POST -H "x-api-key: $KATALIS_API_KEY" -H "Content-Type: application/json" \
  -d '{"company":"00502851","label":"Greggs"}' \
  "https://meetkatalis.com/api/v1/watch"
```

```javascript
const res = await fetch("https://meetkatalis.com/api/v1/watch", {
  method: "POST",
  headers: { "x-api-key": process.env.KATALIS_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({"company":"00502851","label":"Greggs"}),
});
if (!res.ok) throw new Error(`Katalis ${res.status}: ${await res.text()}`);
console.log(await res.json());
```

```python
import os, requests

r = requests.post(
    "https://meetkatalis.com/api/v1/watch",
    headers={"x-api-key": os.environ["KATALIS_API_KEY"]},
    json={"company":"00502851","label":"Greggs"},
    timeout=60,
)
r.raise_for_status()
print(r.json())
```

## Example response (a real reply)

```json
{
  "events": [
    {
      "id": 418,
      "company": "00242246",
      "seenAt": "2026-10-08T06:04:11Z",
      "kind": "payment_report",
      "summary": "SERCO LIMITED filed a new payment practices report: 14 days on average, 6% paid late (was 16 days, 8% late)",
      "before": { "reportId": 113613, "avgDays": 16, "pctLate": 8 },
      "after": { "reportId": 118902, "avgDays": 14, "pctLate": 6 },
      "deliveredToWebhook": true
    }
  ],
  "lastId": 418,
  "more": false
}
```

## What you'd build with it

- **Supplier and subcontractor vetting.** Watch every supplier you've onboarded: a winding-up petition, an overdue filing, a sanctions match or a lost sponsor licence reaches you the day it shows, not at the next annual review.
- **Bid and procurement tools.** Watch the incumbents and the buyers' suppliers: a new contract award or a slipping payment record is a signal your users act on.
- **Lending and credit control.** Watch your debtors: distress signals and overdue accounts before the invoice goes unpaid.
- **Practice software.** Watch every client company: a director change or an ID date still open becomes a task in your own tool.

## Why this one

- **Across the record, not one source.** Companies House, sanctions, payment practices, public contracts and the sponsor register in one watch; a change in any of them is one plain event.
- **Signed webhooks, and a feed.** Each delivery carries X-Katalis-Signature (HMAC-SHA256 of the timestamp and body with your secret); five retries over two days; everything stays in the feed to pull.
- **Honest about what it couldn't read.** A source that was down keeps yesterday's reading and is never reported as a change.
- **Never below cost, never a surprise.** Two credits per company per month, charged on the first read of the month; out of credits, the watch pauses and says so, it isn't dropped.

## Conventions

- Auth: `x-api-key: kat_live_…` on every request (free key at https://meetkatalis.com/developers: a verified email and mobile, 100 credits a month, no card).
- One credit balance across every API; each endpoint's price is on its page and in `x-credits` in https://meetkatalis.com/openapi.yaml.
- Keys are camelCase everywhere. A registered company is `company: { name, number, status, statusDetail?, filingsOverdue? }` on the register endpoints; the enrichment family (enrich, score, assess, brand-kit, ai-visibility, tender-match) keeps `business` / `profile` with `companyNumber`.
- Every error has `code` and `requestId`; every reply an `x-request-id` header; a charged reply `x-credits-remaining`; a reply that gave credits back `x-credits-refunded`. Missing = 404 with `query`.
- Burst ceiling 60 requests a minute per key (429, `Retry-After`, no credits used). A failure on our side (5xx) gives the call's credits back.
- Company data contains public sector information licensed under the Open Government Licence v3.0.

Provided "as is"; results come from public sources and, in places, AI, and may be inaccurate or out of date; not legal, professional or credit advice. Terms: https://meetkatalis.com/apis/terms