API reference
Auth
Sessions, tokens, profiles, two-factor and password reset. docs/11 §1.
Paths are relative to /api/v1 on your server.
/auth/2fa#Read two-factor status
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·TwoFactorStatus - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/2fa/disable#Turn two-factor off
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 204Done; no body.
- 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/2fa/enable#Confirm enrolment and receive recovery codes
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·RecoveryCodes - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/2fa/recovery-codes#Issue fresh recovery codes
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·RecoveryCodes - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/2fa/setup#Begin two-factor enrolment
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·object - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/2fa/verify#Finish a two-factor sign-in
- Authorisation
- None
- Body
application/json·object
- 200Success.
application/json·SignInAnswer - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
AUTH_2FA_INVALID: the code or recovery code is wrongapplication/json·ErrorEnvelope
/auth/forgot#Email a reset link to an account
"Forgot password?": a single-use link, good for an hour, to the email of the account the login (a username or an email) names. The same empty answer whether or not there is such an account, or it has an email; the email goes after the answer. Only when the server sends email and its admins allow it (features.resetByEmail in GET /server/info). Ten asks an hour from an address, three links an hour for an account.
- Authorisation
- None
- Body
application/json·object
- 204Done; no body.
- 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 404
NOT_FOUND: the server does not email reset linksapplication/json·ErrorEnvelope - 429
RATE_LIMITED: more than ten asks in an hour from one addressapplication/json·ErrorEnvelope
/auth/identity-links#List the accounts that sign in with an outside identity
Each account and the identity it answers to — Collectoh, Google, Apple or single sign-on — with the email it gave the last time. Linked, an identity signs in that account alone, whatever the emails say later.
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·object - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lacksuser:manage, or the library, label, age or schedule scope refuses it.application/json·ErrorEnvelope
/auth/identity-links/{id}#Unlink an outside identity from its account
Its next sign-in finds the account by its email again, as a first one does: linked by itself when whoever runs the server gave the account that email, else once the account’s own password is typed. The owner’s, the owner alone.
- Authorisation
- Bearer token or API key · Session cookie
| Parameter | In | Type | Description |
|---|---|---|---|
id required | path | string (uuid) |
- 204Done; no body.
- 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lacksuser:manage, or the library, label, age or schedule scope refuses it.FORBIDDEN: the owner’s, and you are not the ownerapplication/json·ErrorEnvelope - 404
NOT_FOUND: no such thing, or not one the caller may see.NOT_FOUND: no such linked identityapplication/json·ErrorEnvelope
/auth/ldap#Read the directory sign-in settings
Everything but the search account’s password, of which only whether one is kept.
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·object - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lackssettings:manage, or the library, label, age or schedule scope refuses it.application/json·ErrorEnvelope
/auth/ldap#Change the directory sign-in settings
Only what the body names changes. A bindPassword replaces the kept one (sealed at rest, never sent back); null forgets it. The kept one goes only to the addresses, account and certificate settings it was saved with: a change to any of them without a new bindPassword is refused. Switched on, the settings must name an address, a search base and, with a search account, its password.
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·object - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.VALIDATION_FAILED: a setting is not valid, or one that is needed is missingapplication/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lackssettings:manage, or the library, label, age or schedule scope refuses it.application/json·ErrorEnvelope
/auth/ldap/links#List the accounts that sign in by the directory
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·object - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lackssettings:manage, or the library, label, age or schedule scope refuses it.application/json·ErrorEnvelope
/auth/ldap/links#Link an account to a person in the directory
The person the saved settings find by the username given, tied to the account: what a first sign-in does not do by itself for an account whose email was chosen by whoever accepted its invitation. Never the owner. The list of links comes back.
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·object - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lackssettings:manage, or the library, label, age or schedule scope refuses it.FORBIDDEN: the account is the owner’sapplication/json·ErrorEnvelope - 404
NOT_FOUND: no such account, or nobody (or more than one) by that usernameapplication/json·ErrorEnvelope - 409
CONFLICT: the account or the person is linked to another alreadyapplication/json·ErrorEnvelope - 502
PROVIDER_UNAVAILABLE: the directory could not be reached over TLSapplication/json·ErrorEnvelope
/auth/ldap/links/{userId}#Unlink an account from its person in the directory
Its next directory sign-in finds the account by its email again, and links whoever that is.
- Authorisation
- Bearer token or API key · Session cookie
| Parameter | In | Type | Description |
|---|---|---|---|
userId required | path | string (uuid) |
- 204Done; no body.
- 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lackssettings:manage, or the library, label, age or schedule scope refuses it.application/json·ErrorEnvelope - 404
NOT_FOUND: no such thing, or not one the caller may see.NOT_FOUND: the account does not sign in by the directoryapplication/json·ErrorEnvelope
/auth/ldap/login#Sign in with a directory (LDAP) username and password
Into an account that exists here, never a new one (P7-24): the directory finds the person and checks the password; the account is the one their entry was linked to the first time, else the one their email names (or their username, if the server says so). The password form’s limits, lock and two-step sign-in all hold, and its rate-limit buckets are shared. The owner never signs in this way; an admin only when allowAdmins is on. Only while directory sign-in is on (directorySignIn in GET /server/info).
- Authorisation
- None
- Body
application/json·object
- 200Success.
application/json·SignInAnswer - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
AUTH_INVALID_CREDENTIALS: nobody by that username, or a wrong passwordAUTH_2FA_REQUIRED: the directory vouched and a second factor is owed;detailscarries the challenge forPOST /auth/2fa/verifyapplication/json·ErrorEnvelope - 403
AUTH_NO_ACCOUNT: no account here uses the email the directory gives (details.reasonnone); its email was chosen by whoever accepted its invitation, so an admin links it (unvouched); it answers to someone else in the directory, or two accounts match (linked-elsewhere,ambiguous); or the person at a DN-kept link no longer has its email (moved)AUTH_PASSWORD_REQUIRED: the owner, or an admin whileallowAdminsis off: they sign in with their own passwordAUTH_ACCOUNT_LOCKED: too many failures; try again laterFORBIDDEN: not in the required group (details.reasonisldap-group)application/json·ErrorEnvelope - 404
NOT_FOUND: directory sign-in is offapplication/json·ErrorEnvelope - 429
RATE_LIMITED: more than 10 attempts in a minute, by address, name or personapplication/json·ErrorEnvelope - 502
PROVIDER_UNAVAILABLE: the directory could not be reached over TLSapplication/json·ErrorEnvelope
/auth/ldap/test#Try directory settings, and look someone up
The settings as the form has them (what is left out, as saved): reaches the directory over TLS, signs in as the search account, and looks for the username given — never with their password — saying which account it would sign in to and how (person.link). The kept search password is used only with the addresses, account and certificate settings it was saved with; with others, a bindPassword must be typed, or the test stops at settings. Says where it stopped and why.
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·object - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account lackssettings:manage, or the library, label, age or schedule scope refuses it.application/json·ErrorEnvelope
/auth/login#Sign in with a password
Bearer clients receive tokens in the body (accessToken, refreshToken, refreshExpiresAt). The web client sends cookieMode: true and receives HttpOnly cookies instead. Rate limited to 10/min per IP and per username. A browser holding an outside identity that waits for this account’s own password (the co_identity_link cookie an outside sign-in left, docs/11 §5) has it linked to the account — only the account that identity’s email named, once any second factor is in.
- Authorisation
- None
- Body
application/json·object
- 200Success.
application/json·SignInAnswer - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
AUTH_INVALID_CREDENTIALS: the username or password is wrongAUTH_2FA_REQUIRED: the password was right and a second factor is owed;detailscarries the challengeapplication/json·ErrorEnvelope - 403
AUTH_ACCOUNT_LOCKED: too many failures; try again laterapplication/json·ErrorEnvelope - 429
RATE_LIMITED: more than 10 attempts in a minuteapplication/json·ErrorEnvelope
/auth/logout#End the session
- Authorisation
- None
- Body
application/json·object
- 200Success.
application/json·object - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope
/auth/me#Read the signed-in account
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·PublicUser - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/me#Change your own display name
The one part of your own account you may change without users:manage. The whole public user comes back, as GET /auth/me answers it.
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·PublicUser - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/me/password#Change your own password
The current password proves it is you. Every session ends, this one included — sign in again with the new password. Not for an API key.
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 204Done; no body.
- 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.AUTH_INVALID_CREDENTIALS: the current password is wrongapplication/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/me/prefs#Update the account’s preferences
Only what the body names changes. Some preferences are Collectoh Plus’s (docs/14 §6): a theme other than the default, a colour scheme other than dark, a subtitle style, and a sidebar order or pins of the account’s own. Without Plus, changing to one is refused; going back to the default, or sending again what is kept, never is.
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·PublicUser - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 402
PLUS_REQUIRED: the body changes a preference only Plus applies, on a server without it;details.featureisthemes,subtitle-stylesorsidebar-orderapplication/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/private#Say whether private libraries are unlocked on this device
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·object - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/private/lock#Lock private libraries again on this device
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·object - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/private/unlock#Unlock private libraries for an hour, with the account password
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
- 200Success.
application/json·object - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.AUTH_INVALID_CREDENTIALS: the password is wrong (403: the session stands)application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.FORBIDDEN: a child or a guest, who never unlocks themapplication/json·ErrorEnvelope
/auth/profiles#List the profiles this session may switch to
- Authorisation
- Bearer token or API key · Session cookie
- 200Success.
application/json·SwitchableProfile[] - 401
UNAUTHENTICATED: no session, or the access token expired.application/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.application/json·ErrorEnvelope
/auth/profiles/{id}/switch#Switch to another profile
- Authorisation
- Bearer token or API key · Session cookie
- Body
application/json·object
| Parameter | In | Type | Description |
|---|---|---|---|
id required | path | string (uuid) |
- 200Success.
application/json·SignInAnswer - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
UNAUTHENTICATED: no session, or the access token expired.AUTH_PIN_INVALID: the profile has a PIN and it was wrongapplication/json·ErrorEnvelope - 403
FORBIDDEN: the account may not do this.AUTH_PASSWORD_REQUIRED: an owner, an admin or an account with two-step sign-in: it signs in with its passwordapplication/json·ErrorEnvelope - 404
NOT_FOUND: no such thing, or not one the caller may see.application/json·ErrorEnvelope - 429
RATE_LIMITED: five wrong PINs for the profile in a quarter of an hourapplication/json·ErrorEnvelope
/auth/refresh#Rotate the refresh token
Refresh tokens rotate on every use. Reusing a rotated token revokes the whole chain (AUTH_TOKEN_REUSED). An app sends its refresh token in the body and gets the new pair in the answer; the web client sends none (its cookie carries it) and gets cookies.
- Authorisation
- None
- Body
application/json·object
- 200Success.
application/json·SignInAnswer - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 401
AUTH_TOKEN_EXPIRED: the refresh token is older than 30 daysAUTH_TOKEN_REUSED: a rotated token was presented againapplication/json·ErrorEnvelope
/auth/reset#Set a new password from a reset link
- Authorisation
- None
- Body
application/json·object
- 200Success.
application/json·AuthSession - 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope
/auth/reset/{token}#Read what a reset link is for
- Authorisation
- None
| Parameter | In | Type | Description |
|---|---|---|---|
token required | path | string |
- 200Success.
application/json·object - 404
NOT_FOUND: no such thing, or not one the caller may see.application/json·ErrorEnvelope
/auth/sign-in/{provider}#Start an outside sign-in
Redirects to the provider (Collectoh, Google, Apple, an OpenID issuer), leaving a cookie that ties the sign-in to this browser. Only configured providers answer; one that is not answering sends the browser to the login page with the error.
- Authorisation
- None
| Parameter | In | Type | Description |
|---|---|---|---|
provider required | path | string | |
next | query | string | |
prompt | query | "none" | |
client | query | string | |
clientName | query | string |
- 302Success.
- 400
VALIDATION_FAILED: the request did not match the schema;details.issueslists what.application/json·ErrorEnvelope - 404
NOT_FOUND: no such thing, or not one the caller may see.application/json·ErrorEnvelope
/auth/sign-in/{provider}/callback#Finish an outside sign-in
Redirects into the app with a session, or to the login page with an error. Only the browser that started the sign-in finishes it. An identity signs in the account it was linked to, whatever the emails say; the first time, the account carrying the email it vouches for, linked once the sign-in goes through — when whoever runs the server gave the account that email. One its holder chose as they accepted an invitation sends the browser to /login?error=AUTH_LINK_REQUIRED&provider=… with the identity waiting in an HttpOnly cookie (co_identity_link, a quarter of an hour) for that account’s own password (POST /auth/login); asked quietly (prompt=none), it comes back with nothing. An account that answers to another identity there: /login?error=AUTH_NO_ACCOUNT&reason=linked-elsewhere&provider=….
- Authorisation
- None
| Parameter | In | Type | Description |
|---|---|---|---|
provider required | path | string |
- 302Success.
- 404
NOT_FOUND: no such thing, or not one the caller may see.application/json·ErrorEnvelope
/auth/sign-in/{provider}/callback#Finish an outside sign-in (form post)
Only for a provider that answers by POST (Apple, response_mode=form_post), as a form, from the browser that started it (its co_sign_in_post cookie, SameSite=None); otherwise as the GET.
- Authorisation
- None
| Parameter | In | Type | Description |
|---|---|---|---|
provider required | path | string |
- 302Success.
- 404
NOT_FOUND: no such thing, or not one the caller may see.application/json·ErrorEnvelope
No endpoint here matches. Try another word, or look in another area.