Create Session
Verify a sign-in credential and set the HttpOnly session cookie.
The session is bound to the identity that authenticated, so every request it later authenticates resolves a user and that user's active organization rather than only "a credential was presented once". The response names both, so a client knows who it is signed in as without a second call.
The rate-limit check deliberately runs only after a failed verification, not before it: a pre-verification gate can't know whether this attempt would have succeeded, so once an IP has used up its failure quota it would end up blocking that IP's legitimate owner too, not just further attackers. Running after verification also means the throttle bounds how many verdicts an IP gets, not how much work it can cause: a password attempt pays for a bcrypt verification (cost 12, on the order of 200ms of CPU, and one is burned against a stand-in hash even for an address nobody holds) before the limit is consulted, so a 429 costs the same as a 401. A gateway exposed to the internet should rate-limit this path at the proxy as well.
The maintenance-mode check runs before either credential is verified, and refuses both. Before, because a frozen deployment should not spend a bcrypt verification per attempt and the refusal is not about the credential anyway; both, because the way back out is the master key against PATCH /v1/settings/maintenance-mode through the header, which never passes through this door. That is what keeps the way back out off the frozen path, and it is why no identity needs an exemption here; an operator who no longer holds the master key recovers by setting OTARI_MASTER_KEY and restarting, which is a restart rather than a click. It leaks nothing either: GET /v1/bootstrap already publishes the same flag unauthenticated, so the sign-in screen can render the right page.
Request body
Example request
{
"email": "operator@example.com",
"password": "a-real-password"
}Response
Successful Response