Developer Auth
Signup, login, token refresh, logout, and current-developer lookup.
Developer credentials are owned by Amba's Amba API. Passwords are hashed with bcrypt (10-round salt). Refresh tokens are stored as sha256 hashes so a DB dump can't replay them.
Rate limits
Per-IP, two-tier (fast + daily):
| Route | Per minute | Per day |
|---|---|---|
POST /auth/developer/signup | 5 | 50 |
POST /auth/developer/waitlist | 5 | 50 |
POST /auth/developer/login | 10 | 100 |
POST /auth/developer/otp/request | 5 | 50 |
POST /auth/developer/otp/verify | 20 | 200 |
POST /auth/developer/refresh | 30 | — |
otp/request is additionally capped per address (5 per hour, 20 per day). /logout and /me are not rate-limited beyond the global gateway defaults.
POST /auth/developer/signup
Create a new developer and return an access + refresh token pair.
While signups are invite-only, send invite_code, or the call
answers 403 INVITE_REQUIRED. See Getting access for the
signup modes and how to request a code.
Request
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | Unique email address. |
password | string | yes | Minimum 8 characters. Bcrypt-hashed server-side. |
name | string | no | Display name. |
invite_code | string | while invite-only | Invite code from the invite email (AMBA- plus four groups of four letters and digits, such as AMBA-7KQ2-M9XD-4TNB-HR3W; case, spaces, and dashes are ignored). Optional when signups are open. A code that is sent must be valid in every mode. |
Response 201
Errors
400 INVALID_INPUT— missing or malformed email, or missing password.400 WEAK_PASSWORD— password is shorter than 8 characters.400 DISPOSABLE_EMAIL— the address is on a disposable / temporary inbox domain. Use a permanent address.403 INVITE_REQUIRED— signups are invite-only and noinvite_codewas sent.403 INVITE_INVALID— theinvite_codeis mistyped, expired, revoked, or already used.403 SIGNUPS_CLOSED— new accounts are closed for now; invite codes are refused too.409 EMAIL_EXISTS— the email, or an alias of the same mailbox, is already registered. Aliases are matched case-insensitively with any+tagremoved, and with dots ignored for Gmail addresses (j.doe+work@gmail.comandjdoe@gmail.comare the same mailbox). A sent invite code stays unspent.429— rate limited.500 CREATE_FAILED— database error. Inspect server logs.
The three 403 refusals carry where to request access:
Try it:
/auth/developer/signupcurl -X POST 'https://api.amba.dev/v1/auth/developer/signup'Curl:
POST /auth/developer/redeem-invite
For an account that already exists: redeems an invite code so the account can
create projects while access is limited. New accounts pass invite_code at
signup instead. Requires the developer Bearer (session token or PAT).
Response 200: { "data": { "can_provision": true, "redeemed": true } }. An
account that can already create projects gets "redeemed": false and the code
stays unspent.
Errors: 403 INVITE_INVALID (mistyped, expired, revoked, or already used),
403 SIGNUPS_CLOSED (codes are refused while signups are closed),
403 PROVISIONING_REVOKED (project creation was turned off for the account;
contact support), 401 without a valid Bearer, 429 when rate-limited (10
per minute per IP).
POST /auth/developer/waitlist
Request access while new accounts are invite-only or closed. Public, no authentication. When access is granted, Amba emails the address an invite code, a signup link with the code filled in, and a one-line prompt to paste into a coding agent. The console form at app.amba.dev/request-access calls this endpoint.
Request
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | Where the invite code is sent. |
note | string | no | What you're building. The first 500 characters are kept. |
Response 200
Every well-formed email gets this same response, whether or not the address is already listed or already has an account, so the endpoint cannot be used to enumerate accounts. Asking again for the same address is safe; the note from the first request is the one kept.
Errors
400 INVALID_INPUT— body is not JSON,emailis missing or implausible, ornoteis not a string.429— rate limited (5 per minute, 50 per day per IP).429 WAITLIST_FULL— the day's list of new addresses is full. Try again tomorrow.503 WAITLIST_UNAVAILABLE— the request was not recorded. Try again in a few minutes.
Curl:
POST /auth/developer/login
Exchange email + password for tokens.
Request
| Field | Type | Required |
|---|---|---|
email | string | yes |
password | string | yes |
Response 200
Errors
400 INVALID_INPUT— missing email or password.401 INVALID_CREDENTIALS— wrong email or password. (Generic on purpose — never leak whether the email exists.)429 RATE_LIMIT_EXCEEDED— too many attempts from your address (10/min, 100/day), or too many failed password attempts for this account (20/hour, 100/day, counted across every Amba sign-in surface).Retry-Aftersays when to retry; an emailed sign-in code still works in the meantime.500 LOGIN_FAILED.
Try it:
/auth/developer/logincurl -X POST 'https://api.amba.dev/v1/auth/developer/login'Curl:
POST /auth/developer/otp/request
Email a 6-digit sign-in code to an existing developer account. This is the passwordless path: an account that never set a password (for example one created by an agent and later bound to your address) signs in with the code instead. The console's Email me a sign-in code option and amba login use it.
Request
| Field | Type | Required |
|---|---|---|
email | string | yes |
Response 200
The response is the same whether or not an account exists for the address, so it cannot be used to enumerate accounts. Codes expire after 10 minutes, are single-use, lock after 5 wrong attempts, and a new request replaces any code still outstanding.
Errors
400 INVALID_INPUT— missing or implausible email.429 RATE_LIMIT_EXCEEDED— per-IP or per-address limit hit (Retry-Afteris set).500 OTP_REQUEST_FAILED.
POST /auth/developer/otp/verify
Redeem the emailed code for a session. Returns the same envelope as POST /auth/developer/login, and marks the account's email verified (a sandbox account is promoted to verified_free).
Request
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | yes | The address the code was sent to. |
code | string | yes | The 6 digits from the email (spaces are fine). |
Response 200
Identical to POST /auth/developer/login: access_token, refresh_token, developer.
Errors
400 INVALID_INPUT— missing email, or a code that is not 6 digits.401 OTP_INVALID— wrong, expired, already-used, or locked code, or no account for the address. (Generic on purpose.)429— rate limited.500 OTP_VERIFY_FAILED.
Curl:
POST /auth/developer/refresh
Rotate the refresh token. The old session is revoked and a new access + refresh pair are issued. If the same refresh token is presented twice the second call fails — that's how we detect token theft.
Request
| Field | Type | Required |
|---|---|---|
refresh_token | string | yes |
Response 200
Errors
400 INVALID_INPUT.401 INVALID_TOKEN— token signature failed, session not found, expired, or already revoked.429— rate limited.500 REFRESH_FAILED.
Try it:
/auth/developer/refreshcurl -X POST 'https://api.amba.dev/v1/auth/developer/refresh'Curl:
POST /auth/developer/logout
Revoke the session referenced by the refresh token. Idempotent — an already-invalid token returns success.
Request
| Field | Type | Required |
|---|---|---|
refresh_token | string | yes |
Response 200
Errors
400 INVALID_INPUT.500 LOGOUT_FAILED.
Try it:
/auth/developer/logoutcurl -X POST 'https://api.amba.dev/v1/auth/developer/logout'Curl:
GET /auth/developer/me
Return the current developer profile. Requires a valid access token.
Request
Response 200
Errors
401 UNAUTHORIZED— missing or invalid access token.404 NOT_FOUND— the developer the token references no longer exists.500 FETCH_FAILED.
Try it:
/auth/developer/mecurl -X GET 'https://api.amba.dev/v1/auth/developer/me'Curl: