Lede API
Send shift handovers from your own systems, and read your sites, handovers and urgent items, with an API key.
Before You Start
You need the Growth or Enterprise plan. An organisation admin does three things on the Developer page in Lede: turns on Write Access, creates an API key with the Write Handovers permission, and, if you want to send by your own code instead of Lede's site id, sets a code for each site. Write Access is off for every organisation until an admin turns it on. Reading does not need Write Access: a key with the Read sites or Read handovers permission can read on the Growth or Enterprise plan, and a read only key works.
Base URL And Authentication
Requests go to https://app.workwithlede.com/api. The Developer page shows the exact address for your environment. Send your key in the X-Lede-API-Key header. Every response from a versioned route carries Lede-Api-Version: 1.
Send A Handover
POST /v1/handovers creates one handover. It needs the Idempotency-Key header and a JSON body.
curl -X POST "https://app.workwithlede.com/api/v1/handovers" \
-H "X-Lede-API-Key: YOUR_API_KEY" \
-H "Idempotency-Key: YOUR_UNIQUE_REQUEST_ID" \
-H "Content-Type: application/json" \
-d '{
"siteCode": "SYD-01",
"sourceSystem": "Rostering System",
"endedAt": "2026-10-21T07:00:00+11:00",
"items": [
{ "text": "Lift 2 out of service, technician booked for 9 am." },
{ "text": "Night audit done, two late checkouts approved." }
]
}'
| Field | Required | Notes |
|---|---|---|
siteCode or siteId | One of them | Your own site code, or Lede's site id. Never both. |
sourceSystem | Yes | Up to 60 characters. The handover shows as "Imported from" this name. |
items | Yes | 1 to 50 items. Each is { "text": "..." } with up to 4,000 characters. |
endedAt | No | ISO 8601 time with an offset. Defaults to now. Up to 31 days back, never in the future. |
startedAt | No | When the shift began. No later than endedAt and within 24 hours of it. |
authorEmail | No | Attribute the handover to a person. They must be a member of that site, or the request is refused with AUTHOR_NOT_SITE_MEMBER. Leave it out and the handover is attributed to the source system. |
shiftType | No | A short label, up to 40 characters. |
Send only what a handover needs. Please leave out personal information about staff, guests or residents that the handover does not need.
A successful write returns 201 with the handover id, siteId, handoverDate, itemCount and ai. The ai field is processed when Lede summarised the handover, or deferred when it was saved without a summary.
Read Your Data
Four read routes use the same key and base URL. Each answers GET with JSON and Cache-Control: no-store. Reads never change anything.
| Route | Permission | What you get |
|---|---|---|
GET /v1/me | Any valid key | Test a connection. Returns org (id, name), key (scope, scopes: what this key can do), writeAccess.enabled and apiVersion. No people. |
GET /v1/sites | Read sites | Your active sites: id, name, externalCode (your own site code, or null) and group (the group name, or null), in name order, up to 500 sites. Returns { "data": [...] }. |
GET /v1/handovers | Read handovers | Handovers, newest first by when they became visible in Lede (publishedAt). Each has id, siteId, siteName, shiftType, handoverDate, createdAt, publishedAt, source, summary, severity and itemCount. |
GET /v1/urgent-items | Read handovers | Urgent items, newest first by when they became visible (publishedAt). Each has id, handoverId, siteId, siteName, text, createdAt and publishedAt. |
GET /v1/handovers/new | Read handovers | The handovers this key has not been given yet, each served once, newest first. Same fields as /v1/handovers plus deliveredAt, when this feed served it. Returns { "data": [...], "hasMore": false }. |
GET /v1/urgent-items/new | Read handovers | The urgent items this key has not been given yet, each served once, newest first. Same fields as /v1/urgent-items plus deliveredAt. Returns { "data": [...], "hasMore": false }. |
curl "https://app.workwithlede.com/api/v1/handovers?limit=25&source=api" \
-H "X-Lede-API-Key: YOUR_API_KEY"
Order and polling. Lists are ordered by publishedAt, newest first. It is when the row became visible through this API: a handover is published when it is saved, so one written today for last week's shift (see endedAt above) still appears at the top, and an urgent item is published when its handover is saved or when a manager marks it safe. createdAt is the record date (a handover written after the fact carries the shift end, and an urgent item carries the time the note was added), so do not keep a high-water mark on it: use publishedAt. An id can appear again with a later publishedAt, for example after a hidden or archived handover is restored, or when a manager marks an item safe again after undoing it, so dedupe on id. handoverDate is when the shift ended.
Pagination. /v1/handovers and /v1/urgent-items take limit (1 to 100, default 25) and cursor. A page returns { "data": [...], "nextCursor": "..." }. Send nextCursor back as cursor to get the next page. It is null on the last page. A cursor is opaque text, so store it and pass it back unchanged. One that this API did not issue is refused with INVALID_CURSOR. To poll, read from the top and stop at the first id you have already seen.
Once-only feeds. /v1/handovers/new and /v1/urgent-items/new are for triggers that must act on each item once, even when a handover is restored (within 90 days) and its publishedAt moves. They take limit (1 to 100, default 25), siteId and, on handovers, source, but no cursor: Lede remembers what each key has been given. The first poll returns a sample of the newest items, not the backlog, so you can set up against real data; every later poll returns what was published since. Each item carries deliveredAt. An item is served again, after newer items, on polls within 60 minutes of first being served, in case a response was lost; after that it is final, so dedupe on id. Items are returned with the most recently served first. Anything published more than 30 days ago is never served. hasMore is true when more items are waiting than limit: poll again. It is always false on the first poll. Add consumer (letters, digits, - and _, up to 64) to give each reader behind one key its own position. Each consumer and siteId or source filter combination is a separate reader, and a key can hold up to 20 readers per key per feed before the API returns FEED_CONSUMER_LIMIT (409). A rotated key starts fresh: it is a new key, so its first poll is a sample again, with each item's deliveredAt dated as published.
Filters. Both lists take siteId. /v1/handovers also takes source: app (written in Lede), api (sent through the write API) or import (a history import). A siteId that is not yours returns an empty list.
What is left out. Archived and hidden handovers, handovers older than your plan's history window, and sites you have removed or archived. Anything Lede has flagged for care, and any item its safety check has not finished screening, is never returned, and the counts, severity and count-style summaries are worked out without it. Items sent through the write API are not screened, so they count towards neither itemCount nor /v1/urgent-items. Reads show no names, photos or email addresses: a handover is not attributed to a person. Text over 2,000 characters is cut and ends with …. When any item of a handover is left out, its summary is replaced by a plain count such as 2 items or quiet shift.
Retries And Idempotency
Every write needs an Idempotency-Key of 1 to 128 letters, numbers or . _ : - characters, one per handover (for example your roster shift id). Send the same key and the same body again and you get the original answer back with 200 and an Idempotent-Replayed: true header. No second handover is created. The same key with a different body is refused with IDEMPOTENCY_KEY_REUSED. Keys are remembered for 7 days.
AI Summaries And Limits
- Each key gets the AI summary on its first 50 handovers in any 24 hours. After that, handovers are still saved, without the summary, and the response says
ai: "deferred". A write is never refused because of the AI. - Up to 60 writes a minute per key, and up to 60 requests a minute from one IP address. Over either you get
429withRATE_LIMITED. Back off and retry with the sameIdempotency-Key. - Reads have their own limits: up to 120 requests a minute per key, then
429withRATE_LIMITED. Every request, reads and writes together, also counts towards a ceiling of 300 a minute from one IP address, and a request over it gets429. Too many requests with a key that is not valid are also refused with429. - The request body can be up to 1.25 MB, enough for 50 items of 4,000 characters even when non-ASCII text is escaped.
Error Codes
Every error carries a code to branch on. The wording of error can change.
| Code | Status | Meaning |
|---|---|---|
API_WRITE_DISABLED | 403 | Write Access is off for the organisation. |
API_ACCESS_REQUIRED | 403 | The organisation's plan does not include API access. Checked on every request, reads included. |
API_KEY_REQUIRED | 401 | No valid API key was sent. |
API_KEY_READ_ONLY | 403 | The key is read only. |
API_KEY_SCOPE_FORBIDDEN | 403 | The key does not have the permission the route needs: Write Handovers to send, Read sites for /v1/sites, Read handovers for /v1/handovers and /v1/urgent-items. |
INVALID_REQUEST | 400 | The body or query failed validation. The message names the field. |
INVALID_CURSOR | 400 | The cursor was not issued by this API. |
IDEMPOTENCY_KEY_REQUIRED | 400 | No Idempotency-Key header. |
IDEMPOTENCY_KEY_INVALID | 400 | The Idempotency-Key has characters or a length that is not allowed. |
SITE_NOT_FOUND | 404 | No site in your organisation has that id or code. |
AUTHOR_NOT_SITE_MEMBER | 422 | authorEmail is not a member of that site. |
HANDOVER_NOT_ENABLED | 422 | Handover is switched off for that site. |
TOO_MANY_SOURCE_SYSTEMS | 422 | An organisation can use up to 25 different sourceSystem names. |
IDEMPOTENCY_KEY_REUSED | 409 | That key was already used with a different body. |
IDEMPOTENCY_IN_PROGRESS | 409 | A request with that key is still being processed. Retry shortly. |
RATE_LIMITED | 429 | Over 60 writes or 120 reads a minute for this key, over 60 write requests a minute from one IP address, or too many requests with a key that is not valid. Going over 300 requests a minute of any kind from one IP address is also a 429, but with no code in the body. |
Versioning And Deprecation
This is version 1 of the API, at /v1. Within a version we only add: new optional request fields, new response fields and new error codes. Build clients that ignore fields they do not know. Nothing is removed or changed in a way that breaks a working client without at least 12 months' notice. During the notice period every response from a deprecated version carries a Deprecation header (the date it was deprecated, as @ and Unix seconds), a Sunset header with the date it will stop working (an HTTP date, sent once that date is set) and a Link header with rel="deprecation" pointing to this section. A retired version answers 410 Gone with a message naming the version to use instead. The same headers apply to the MCP server at /api/mcp. A current version sends none of them.
Other Routes
POST /intelligence/signalsqueues a signal from a plugin or integration. It is unchanged.GET /intelligence/snapshotfetches your organisation's latest snapshot. It is unchanged.
Help
Email info@workwithlede.com. See also Support and the FAQ.