Authentication
Dashboard user authentication (password login, sessions, RBAC)
POST /auth/signup Sign up (self-serve org provisioning)
Create a user, provision a new organization + `owner` membership, and send a verification email. Decoupled from auto-login: NO session cookie is set on any branch, and the response is header-identical for new vs existing emails (enumeration-safe). The first session is established via `POST /auth/login` after email verification.
Request body
Responses
201 Account creation accepted (verify your email, then sign in)
400 Invalid request parameters application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/signup" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "string",
"password": "string",
"name": "string",
"org_name": "string"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/signup', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "string",
"password": "string",
"name": "string",
"org_name": "string"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/login Log in (password)
Verify credentials, rotate the session (fixation defence), and set the `httpOnly` + `Secure` + `SameSite=Lax` session cookie and the `__Secure-` CSRF cookie. Requires a verified email. Rate-limited and lockout-guarded; unknown-email, wrong-password, locked, and unverified all return an identical generic failure (enumeration-safe).
Request body
Responses
200 Authenticated; session + CSRF cookies set
401 Missing or invalid API key application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/login" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "string",
"password": "string"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/login', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "string",
"password": "string"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/logout Log out
Revoke the current session (Redis DEL + Postgres `revoked_at`) and clear the cookies.
Parameters
Responses
401 Missing or invalid API key application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/logout" \
-H "Authorization: Bearer $AMPR_API_KEY"
const res = await fetch('https://api.ampr.dev/v1/auth/logout', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
},
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
GET /auth/me Current authenticated user
The current user, their active org, live role, and full membership list (org-switcher).
Responses
200 Current session context
401 Missing or invalid API key application/problem+json
Request example
curl -X GET "https://api.ampr.dev/v1/auth/me" \
-H "Authorization: Bearer $AMPR_API_KEY"
const res = await fetch('https://api.ampr.dev/v1/auth/me', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
},
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/verify-email Verify email
Consume a single-use, hashed, expiring `verify_email` token and mark the account verified.
Request body
Responses
400 Invalid request parameters application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/verify-email" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "string"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/verify-email', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"token": "string"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/verify-email/resend Resend the verification email
Re-issue a verification token. Enumeration-safe and rate-limited (per-email + per-IP, fail-closed): the response is identical whether the email is unknown, already verified, or pending.
Request body
Responses
200 Fixed, enumeration-safe response
400 Invalid request parameters application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/verify-email/resend" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "string"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/verify-email/resend', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "string"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/forgot-password Request a password reset
Issue a single-use reset token by email if the account exists. Enumeration-safe (identical response whether or not mail is sent) and rate-limited per-email + per-IP (fail-closed).
Request body
Responses
200 Fixed, enumeration-safe response
400 Invalid request parameters application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/forgot-password" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "string"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/forgot-password', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "string"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/reset-password Reset password
Consume a single-use `reset_password` token, set the new password, and revoke ALL of the user's sessions (Redis + Postgres).
Request body
Responses
400 Invalid request parameters application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/reset-password" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "string",
"password": "string"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/reset-password', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"token": "string",
"password": "string"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.
POST /auth/switch-org Switch active organization
Change the session's active org to another the user is a member of. Rotates the session (revokes the old id, mints a new one pinned to the new org).
Parameters
Request body
Responses
200 Active org switched; session rotated
403 Authenticated but not authorized for this action (insufficient role) application/problem+json
Request example
curl -X POST "https://api.ampr.dev/v1/auth/switch-org" \
-H "Authorization: Bearer $AMPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"org_id": "org_example"
}'
const res = await fetch('https://api.ampr.dev/v1/auth/switch-org', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AMPR_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"org_id": "org_example"
}),
});
const data = await res.json();
This endpoint requires an API key. Send it as a Bearer token in the Authorization header.