Developers

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." }
    ]
  }'
FieldRequiredNotes
siteCode or siteIdOne of themYour own site code, or Lede's site id. Never both.
sourceSystemYesUp to 60 characters. The handover shows as "Imported from" this name.
itemsYes1 to 50 items. Each is { "text": "..." } with up to 4,000 characters.
endedAtNoISO 8601 time with an offset. Defaults to now. Up to 31 days back, never in the future.
startedAtNoWhen the shift began. No later than endedAt and within 24 hours of it.
authorEmailNoAttribute 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.
shiftTypeNoA 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.

RoutePermissionWhat you get
GET /v1/meAny valid keyTest a connection. Returns org (id, name), key (scope, scopes: what this key can do), writeAccess.enabled and apiVersion. No people.
GET /v1/sitesRead sitesYour 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/handoversRead handoversHandovers, 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-itemsRead handoversUrgent items, newest first by when they became visible (publishedAt). Each has id, handoverId, siteId, siteName, text, createdAt and publishedAt.
GET /v1/handovers/newRead handoversThe 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/newRead handoversThe 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 429 with RATE_LIMITED. Back off and retry with the same Idempotency-Key.
  • Reads have their own limits: up to 120 requests a minute per key, then 429 with RATE_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 gets 429. Too many requests with a key that is not valid are also refused with 429.
  • 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.

CodeStatusMeaning
API_WRITE_DISABLED403Write Access is off for the organisation.
API_ACCESS_REQUIRED403The organisation's plan does not include API access. Checked on every request, reads included.
API_KEY_REQUIRED401No valid API key was sent.
API_KEY_READ_ONLY403The key is read only.
API_KEY_SCOPE_FORBIDDEN403The 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_REQUEST400The body or query failed validation. The message names the field.
INVALID_CURSOR400The cursor was not issued by this API.
IDEMPOTENCY_KEY_REQUIRED400No Idempotency-Key header.
IDEMPOTENCY_KEY_INVALID400The Idempotency-Key has characters or a length that is not allowed.
SITE_NOT_FOUND404No site in your organisation has that id or code.
AUTHOR_NOT_SITE_MEMBER422authorEmail is not a member of that site.
HANDOVER_NOT_ENABLED422Handover is switched off for that site.
TOO_MANY_SOURCE_SYSTEMS422An organisation can use up to 25 different sourceSystem names.
IDEMPOTENCY_KEY_REUSED409That key was already used with a different body.
IDEMPOTENCY_IN_PROGRESS409A request with that key is still being processed. Retry shortly.
RATE_LIMITED429Over 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/signals queues a signal from a plugin or integration. It is unchanged.
  • GET /intelligence/snapshot fetches your organisation's latest snapshot. It is unchanged.

Help

Email info@workwithlede.com. See also Support and the FAQ.

Ask Lede

Questions about the product, pricing, or getting started.

Hi! I can answer questions about how Lede works, what it costs, and how to book a call. What would you like to know?
Ask Lede is AI and can make mistakes. Please note, by continuing, you agree to the terms of our privacy policy. This conversation will be recorded.