Amba

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):

RoutePer minutePer day
POST /auth/developer/signup550
POST /auth/developer/waitlist550
POST /auth/developer/login10100
POST /auth/developer/otp/request550
POST /auth/developer/otp/verify20200
POST /auth/developer/refresh30—

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

POST /auth/developer/signup
Content-Type: application/json
FieldTypeRequiredDescription
emailstringyesUnique email address.
passwordstringyesMinimum 8 characters. Bcrypt-hashed server-side.
namestringnoDisplay name.
invite_codestringwhile invite-onlyInvite 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

{
  "data": {
    "access_token": "eyJ…",
    "refresh_token": "eyJ…",
    "developer": {
      "id": "…",
      "email": "…",
      "name": "…",
      "oauth_providers": [],
      "created_at": "…",
      "updated_at": "…"
    }
  }
}

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 no invite_code was sent.
  • 403 INVITE_INVALID — the invite_code is 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 +tag removed, and with dots ignored for Gmail addresses (j.doe+work@gmail.com and jdoe@gmail.com are 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:

{
  "error": {
    "code": "INVITE_REQUIRED",
    "message": "Amba signups are invite-only right now. Sign up again with an invite code (invite_code), or request access at https://app.amba.dev/request-access.",
    "details": {
      "request_access_url": "https://app.amba.dev/request-access",
      "request_access_endpoint": "POST /v1/auth/developer/waitlist"
    }
  }
}

Try it:

POST/auth/developer/signup
public auth
curl -X POST 'https://api.amba.dev/v1/auth/developer/signup'

Curl:

curl -X POST '${BASE_URL}/auth/developer/signup' \
  -H 'Content-Type: application/json' \
  -d '{}'

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).

POST /auth/developer/redeem-invite
Authorization: Bearer <token>
Content-Type: application/json
 
{ "invite_code": "<code>" }

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

POST /auth/developer/waitlist
Content-Type: application/json
FieldTypeRequiredDescription
emailstringyesWhere the invite code is sent.
notestringnoWhat you're building. The first 500 characters are kept.

Response 200

{ "data": { "ok": true } }

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, email is missing or implausible, or note is 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:

curl -X POST '${BASE_URL}/auth/developer/waitlist' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "you@company.com", "note": "Building a habit tracker in Expo" }'

POST /auth/developer/login

Exchange email + password for tokens.

Request

POST /auth/developer/login
Content-Type: application/json
FieldTypeRequired
emailstringyes
passwordstringyes

Response 200

{
  "data": {
    "access_token": "eyJ…",
    "refresh_token": "eyJ…",
    "developer": {
      "id": "…",
      "email": "…",
      "name": "…",
      "oauth_providers": [],
      "created_at": "…",
      "updated_at": "…"
    }
  }
}

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-After says when to retry; an emailed sign-in code still works in the meantime.
  • 500 LOGIN_FAILED.

Try it:

POST/auth/developer/login
public auth
curl -X POST 'https://api.amba.dev/v1/auth/developer/login'

Curl:

curl -X POST '${BASE_URL}/auth/developer/login' \
  -H 'Content-Type: application/json' \
  -d '{}'

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

POST /auth/developer/otp/request
Content-Type: application/json
FieldTypeRequired
emailstringyes

Response 200

{ "data": { "ok": true } }

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-After is 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

POST /auth/developer/otp/verify
Content-Type: application/json
FieldTypeRequiredNotes
emailstringyesThe address the code was sent to.
codestringyesThe 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:

curl -X POST '${BASE_URL}/auth/developer/otp/request' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "you@company.com" }'
 
curl -X POST '${BASE_URL}/auth/developer/otp/verify' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "you@company.com", "code": "123456" }'

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

POST /auth/developer/refresh
Content-Type: application/json
FieldTypeRequired
refresh_tokenstringyes

Response 200

{ "data": { "access_token": "eyJ…", "refresh_token": "eyJ…" } }

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:

POST/auth/developer/refresh
public auth
curl -X POST 'https://api.amba.dev/v1/auth/developer/refresh'

Curl:

curl -X POST '${BASE_URL}/auth/developer/refresh' \
  -H 'Content-Type: application/json' \
  -d '{}'

POST /auth/developer/logout

Revoke the session referenced by the refresh token. Idempotent — an already-invalid token returns success.

Request

POST /auth/developer/logout
Content-Type: application/json
FieldTypeRequired
refresh_tokenstringyes

Response 200

{ "data": { "success": true } }

Errors

  • 400 INVALID_INPUT.
  • 500 LOGOUT_FAILED.

Try it:

POST/auth/developer/logout
developer auth
curl -X POST 'https://api.amba.dev/v1/auth/developer/logout'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

Curl:

curl -X POST '${BASE_URL}/auth/developer/logout' \
  -H 'Authorization: Bearer ${DEV_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{}'

GET /auth/developer/me

Return the current developer profile. Requires a valid access token.

Request

GET /auth/developer/me
Authorization: Bearer <developer-access-token>

Response 200

{
  "data": {
    "id": "…",
    "email": "…",
    "name": "…",
    "oauth_providers": [],
    "created_at": "…",
    "updated_at": "…"
  }
}

Errors

  • 401 UNAUTHORIZED — missing or invalid access token.
  • 404 NOT_FOUND — the developer the token references no longer exists.
  • 500 FETCH_FAILED.

Try it:

GET/auth/developer/me
developer auth
curl -X GET 'https://api.amba.dev/v1/auth/developer/me'
Loading auth… Configure auth in the settings drawer (top-right) to run this request.

Curl:

curl -X GET '${BASE_URL}/auth/developer/me' \
  -H 'Authorization: Bearer ${DEV_TOKEN}'