Skip to main content

Field names are case-sensitive

Field names in your request payload must match the board schema exactly, including capitalisation. If your board has a field called Status, passing status or STATUS will not map to it. Fetch the board schema first to confirm the exact casing of every field name before building your integration.
curl "https://app.getaptly.com/api/schema/YOUR_BOARD_ID" \
  -H "x-token: YOUR_API_KEY"

Unknown fields are silently ignored by default

If you pass a field name in your request payload that does not exist on the board, Aptly will not throw an error. The field will be silently ignored and the card will still be created or updated without it. To change this behaviour, enable Create Fields in Card Sources. With that setting on, unknown keys will automatically generate new fields on the board instead of being dropped.

_id behaviour depends on your Update Mode setting

Passing an _id in your request body does not always trigger an update. The behaviour depends on the Update Mode configured in Card Sources for that board.
  • Always Create New — the _id field is ignored and a new card is always inserted
  • Update if exists — if a card matching the _id is found, it is updated; otherwise a new card is created
Check your Card Sources settings if updates are not behaving as expected.

Pagination is 0-indexed with no total count

The page parameter starts at 0, not 1. There is no total, hasMore, or nextPage field in the response. The only way to know you have reached the end of the results is to receive an empty array.
# First page
curl "https://app.getaptly.com/api/aptlet/YOUR_BOARD_ID?page=0" \
  -H "x-token: YOUR_API_KEY"

# Second page
curl "https://app.getaptly.com/api/aptlet/YOUR_BOARD_ID?page=1" \
  -H "x-token: YOUR_API_KEY"
Stop paginating when you receive [].

Webhook signatures are plain string matches, not HMAC

The webhook signing key shown in Card Sources is sent as-is in the x-signingKey header of every webhook request. Verifying it is a simple string comparison, not a cryptographic HMAC check.
signing_key = request.headers.get("x-signingKey")
if signing_key != YOUR_STORED_SIGNING_KEY:
    return 403
Because the key is transmitted with every request, treat it like a password and regenerate it immediately if it is ever exposed.

Webhooks retry indefinitely

If your webhook endpoint returns anything other than a 200, Aptly will keep retrying the request indefinitely. There is no retry limit or backoff cap. If you need to take your endpoint offline for maintenance, update the Webhook URL in Card Sources to a temporary endpoint that returns 200 while you work. Restore it when you are done.

Respond to webhooks quickly

Aptly expects your webhook endpoint to respond within 60 seconds. If your handler does time-consuming work such as database writes or downstream API calls, return 200 immediately and process the payload asynchronously in a background job.