Guide

Webhooks vs polling

Both delivery mechanisms read from the same underlying data — pick whichever fits how your system is built, or use both.

Webhooks

Register a URL and we push a signed HTTP POST to it the moment a matching event is ready to deliver. Best if you want real-time delivery and don't want to manage your own polling schedule.

Verifying the signature

Every delivery carries a CompanyWatch-Signature header in the form t={timestamp},v1={signature} — both values are packed into that one header, not sent separately. Split it on the comma, then split each part on =, to get the timestamp and the signature. The signature itself is an HMAC-SHA256 over the string {timestamp}.{body}, keyed with your webhook's signing secret. Recompute it on your end and compare before trusting the payload.

// Pseudocode
const [tPart, vPart] = signatureHeader.split(',')          // "t=1755600000", "v1=9f86d081..."
const timestamp = tPart.split('=')[1]
const signatureFromHeader = vPart.split('=')[1]

expected = HMAC_SHA256(signingSecret, `${timestamp}.${rawBody}`)
if (!constantTimeEquals(expected, signatureFromHeader)) reject()

Retry behaviour

If your endpoint doesn't respond with a 2xx, we retry up to eight times over approximately two hours. Almost everything is retried, including ordinary 4xx responses, on the assumption that a failure during a deploy is usually transient. After the final attempt, the delivery is dead-lettered rather than lost silently.

Polling

Call /v1/updates to get everything new since your last call, in order. There are two ways to use it, depending on whether you want the server to keep track of your position for you or you want to control it yourself.

Letting the server track your position is the simplest method: call the endpoint with no since parameter at all and it will return all updates since you last polled. The downside is if there is a failure your side after you've received the results but before you've processed them, those updates will be lost as a subsequent call to the polling endpoint will not return them again.

curl "https://api.company-watch.co.uk/v1/updates" \
  -H "Authorization: Bearer YOUR_API_KEY"

Tracking the last processed update yourself protects you from a failure your side but requires you to store the current position of your feed. Pass that position explicitly as ?since=, using either a nextCursor from an earlier response or the id of the last update you processed. You should also use this method if two or more processes are polling and you want them both to receive all updates.

Either way, treat the cursor as an opaque string and don't parse or construct one yourself. For the full set of query parameters, response fields, and paging behaviour, see the /v1/updates operation in the API reference.

Which should I use?

  • Webhooks — you want real-time delivery and can expose a public HTTPS endpoint.
  • Polling — you'd rather control the schedule yourself, or you're integrating from somewhere that can't easily receive inbound webhooks.
  • Both — plenty of integrations use polling as a backstop even with webhooks registered, in case a delivery is ever missed.

← Back to quickstart