API & webhooks

Yes, it connects to your system

A REST API over everything in the product and signed webhooks for everything that happens in it. Keys are made in Settings, scoped to one workspace, and revocable. No partner programme, no sales call, no waiting list.

METHODPATHWHAT IT DOES
GET/api/v1/candidatesEvery candidate, newest first. Paged.
GET/api/v1/candidates/{id}One candidate with their applications and current stage.
POST/api/v1/candidatesPut somebody in the database. Refuses a duplicate email and hands back the id of the record that already exists.· needs a write key
GET/api/v1/jobsOpen and closed roles, with the department each belongs to.
POST/api/v1/jobsOpen a role in a department. The department is checked against your workspace before the role is made.· needs a write key
GET/api/v1/clientsThe departments you hire for.
POST/api/v1/clientsAdd a department. Refuses a duplicate name and hands back the id of the record that already exists.· needs a write key
GET/api/v1/applicationsWho is on which role, and what stage they are at.
GET/api/v1/placementsConfirmed hires, with start dates.
GET/api/v1/invoicesBilling records, kept for integrations that already read them — see the note on names below. Needs a key that may see money.
GET/api/v1/webhooksThe subscriptions this workspace has.
POST/api/v1/webhooksSubscribe a URL to one or more events.· needs a write key
DELETE/api/v1/webhooks/{id}Stop a subscription.· needs a write key

What you need to know before you write a line

The questions everybody asks in the first minute.

Authentication

A key per workspace, sent as `Authorization: Bearer sk_live_…`. Keys are made in Settings → API & webhooks and shown once. Two scopes: read, and write which implies read. There is no third level worth the screen it would need.

Why it says clients and placements

The API was named before the product became a company's own hiring system, and a name in a `v1` path does not change under an integration. In the API, a `client` is a department and a `placement` is a hire: `/api/v1/clients` lists your departments and `/api/v1/placements` your hires. `/api/v1/invoices` comes from the same history and stays for anything already reading it.

What you can and cannot write

You can create a candidate, a department and a role, and manage webhooks. You cannot move somebody to Offered, make an offer or record a hire. The three you can create are the ones an integration actually asks for — a form on your own site, a spreadsheet in Zapier, an HRMS pushing applicants, a department's own system opening a requirement — and each is “put this record in the database”, where the rules are ours and a script cannot get them wrong. The rest is judgement, and an API that lets a script move somebody to Offered is an API that will move somebody to Offered by accident.

Rate limit

600 requests a minute per key. Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, so a client can slow down before it is told to; a refusal is a 429 with `Retry-After`. The limit exists to stop a loop with no delay in it, which is the commonest integration bug there is.

Paging

`?page=` and `?pageSize=` on every list, with `?q=` for a text search. Responses carry `rows`, `total`, `page` and `pageSize` — the same shape everywhere, so a client written against one list works against all of them.

Errors

One shape: `{ "error": "…" }` with a real HTTP status, and `detail` where there is something useful to say. Never a 200 with a failure inside it.

Webhooks

Delivered as a POST with a JSON body and a `x-atsway-signature` header: `sha256(timestamp.body)` with your endpoint's secret, the same scheme Stripe and GitHub use. Verify it before you trust the body. Failed deliveries are retried with a backoff, and the attempts are visible in Settings.

Zapier and Make

Both work today with nothing extra to install: a webhook subscription is the trigger, and the REST endpoints are the actions. There is no separate connector because there is nothing for one to do.

Versioning

The path carries the version. `v1` will not change shape under you — a field may be added, never removed or renamed. Anything that has to break becomes `v2` beside it.

Everything you can subscribe to

Deliberately not every event in the product. A feed full of noise is one nobody keeps subscribed to.

candidate.appliedSomebody applied through the careers page
candidates.importedA batch of applicants was imported
application.submittedA candidate was shortlisted for a hiring manager
application.stage_changedAn application moved stage
application.rejectedAn application was rejected
interview.scheduledAn interview was booked
interview.feedbackInterview feedback was recorded
client.decisionA hiring manager said yes or no in their portal
placement.extendedA fixed-term hire was extended

A first request

curl https://your-instance.example/api/v1/candidates \
  -H "Authorization: Bearer sk_live_…"

# create one
curl https://your-instance.example/api/v1/candidates \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"Priya Sharma","email":"[email protected]","skills":["React"]}'

The host is your own instance — this product is delivered, not shared, so there is no api.lsats.com holding everybody’s data behind one door.

Connecting it to something of yours?

Keys are made by an administrator under Settings, scoped to what the integration needs and revocable at any time.