Changelog

.md

Every change to the public API, newest first.

2026-10-16

2026-10-15

  • New: the admin endpoints under /v1/admin, for the Propper app, starting with the admin profile and the sidebar. They need a token signed in with "app": "admin" and the new scopes admin:read and admin:write, which no other app is granted.
  • Signing in with "app": "admin" refuses an account that does not help run the environment, with 403 admin_access_required.
  • New error codes workspace_required and platform_required, and forbidden on an admin endpoint names the missing permission in required_permission.
  • locale on your profile is null for an account that never chose a language. It always could be, the page now says so.
  • Push registration takes "app": "admin" for the Propper app, which gets the mail and calendar notifications as well.
  • Signing in with "app": "admin" to an account that has to have two-factor and has none answers with a setup step instead of two_factor_setup_required: a secret, then the first code, which signs in and hands out the recovery codes once.
  • A signed-in app can change its name and language, its picture and its password, and set up or turn off an authenticator, with its recovery codes.
  • Your profile says which second factors you have, in two_factor_methods.
  • An environment's branding carries primary_foreground and primary_foreground_dark, the colour the firm writes on its own colour.
  • An environment's branding carries icon_url, a square of at most 512 pixels made from the firm's favicon, for showing the firm in a small space.
  • reminders on an appointment are only ever yours, as the page always said, and a change replaces only yours. On a shared calendar they used to be everybody's, and a change took the others' away.
  • New: what waits for you, the dashboard's attention queue, with the new error code invalid_kind.
  • New: notification settings, one switch per kind of notice, which silences the bell, the push and the mail of that kind at once. Changing them answers with invalid_kind for a kind the account does not receive.
  • New notices for admins when a payout waits to be reviewed or paid, an affiliate applies, asks for a code or asks for a payout: in the notification centre and, on a device registered as admin, as a push of the new type admin.notification. Every other notice for admins and for Propper's staff arrives that way too.
  • New: the dashboard's money, what is owed to funded traders and traders and accounts, per period, with the new error code invalid_period.

2026-10-11

  • A rotated key can keep its old secret working beside the new one for an hour, a day or a week, chosen by whoever rotates it. During that time a call with either secret is accepted. See Rotating and revoking.
  • An IP allowlist entry is checked when it is saved, so an entry that is not an IPv4 or IPv6 address or a CIDR range can no longer end up on a key and refuse every call.

2026-10-08

  • New ids are 16 characters after the prefix instead of 24, such as wl_k7m2p9x4q8r3t6v5. Ids handed out before keep working. Treat an id as an opaque string and do not check its length.
  • The calendar names calendars, appointments and labels by string ids such as evt_k7m2p9x4q8r3t6v5 instead of numbers: id, calendar_id and the label ids in every response, calendars[], calendar_id and tag_ids[] in requests, /v1/me/calendar/events/{id}, the invitation on a mail conversation and event_id in a reminder push. A number in a URL or in calendars[] finds nothing, and one in a body is refused with validation_failed.
  • Calendars carry a channel, the socket channel to subscribe to for that calendar. Use it as it is rather than building one from id.
  • Your profile and everything under /v1/me/mail name rows by string ids such as msg_h3k8q2w7n4r9t5vx instead of numbers: id on /v1/me and on every mailbox, label, signature, assignee, blocked sender, message, note and attachment, and every field that points at one, such as thread_id, address_id, mailbox_id, author_id, user_id, reply_to_id, signature_id, the label ids, assignee, answered, deleted in the sync and both sides of meta.defaults on the signatures. The prefix says what an id names, see Reading mail. The public_id, author_public_id and user_public_id fields are gone, because id, author_id and user_id now carry the same value.
  • Requests take those ids as well: every path under /v1/me/mail, the mailbox and label filters, label_id and user_id, and address_id, in_reply_to, draft_id and signature_id on a send, a draft and the writing help. A number in a path or in the label filter answers 404, one in the mailbox filter is ignored like any mailbox you cannot read, and one in a body is refused with validation_failed.
  • Your profile and each mailbox carry a channel, the socket channel your notifications and that mailbox's new mail arrive on. Use it as it is rather than building one from id.
  • The channel on your profile names you by your string id, such as private-App.Models.User.usr_hraj4wtnqgrkeu9b, instead of a number. /v1/me/broadcasting/auth refuses the old name with channel_not_allowed, so subscribe to the value /v1/me gives you now. The channel of each mailbox changes the same way, such as private-mail-address.mbx_w6sy3skvgydh5e3b.
  • The channel of each calendar names it by its string id too, such as private-calendar.cal_r4d8h2m6t9w3k7nb, and the old name is refused the same way. calendar.changed carries that id as calendar_id, so it now matches the id in the calendar list.
  • Notifications on that channel no longer carry user_token_id, ticket_id, fraud_flag_id or tenant_id. They were internal numbers that matched nothing else in this API.
  • mail.received names the message, its conversation and its mailbox by the same string ids, and so do push notifications: user_id in a mail or reminder push, and message_id, thread_id and mailbox_id in a mail push. Mail notifications still stack per mailbox, under a thread-id that now carries the mailbox's string id.
  • A list cursor or a sync next_since from before this change is refused with invalid_cursor or invalid_since. Rebuild a cached mailbox from the list: every id in it was a number.
  • Workspaces keep their slug, or platform, as id. They never carried a number, so the Propper-Workspace header and workspace in a push stay as they were.

2026-08-04

  • Added the launch waitlist: create, list, retrieve, resend and unsubscribe under /v1/waitlist/signups.
  • Added the waitlist:read and waitlist:write scopes. Existing keys do not have them; tick the boxes on the key that needs them.

2026-08-03

First release of v1.

  • GET /v1/ping for verifying a credential.
  • Affiliate pre-registration: create, list, retrieve, resend and withdraw.
  • API keys, scopes, idempotency, cursor pagination and rate limits.