Public API

/signup.ashx · public API

Create a CodeB user account programmatically. Same code path as the website’s signup form. The created user lands in the guest role with disabled=true and stays unable to sign in until the activation link is clicked.

Plaintext passwords never traverse the wire. The browser computes HA1 = MD5(user:realm:password) and submits only the HA1. The server stores HA1 verbatim; sign-in uses the same digest scheme as the SIP credentials store, so a single credential works for the WebRTC site, the OIDC IdP, and a registered SIP softphone. Personal data handling is described in the public privacy notice.

POST /signup.ashx #

Create a new user account on this tenant. The user is created with disabled=true and role=guest; an activation email is dropped into the SMTP pickup directory and the user can sign in after clicking the link.

Request

Form fields:

  • user[a-z0-9_.-]{1,64}, must be unused and not a reserved name
  • name — 1–120 chars, displayed name
  • email — valid shape, used for the activation link
  • ha1MD5(user:realm:password), 32 hex (browser computes it)
  • captcha_token, captcha_answer — from /captcha.ashx

Response

{ "ok": true, "user": "<username>" }

Errors (verified 2026-06-05)

  • 400 invalid_request — missing field, bad shape, reserved username, HA1 not 32 hex.
    {"error":"invalid_request","error_description":"user, name, email, ha1, captcha_token, captcha_answer required"}
  • 400 captcha_failed — token or answer do not match.
    {"error":"captcha_failed","error_description":"…"}
  • 405 — non-POST request.
  • 409 conflict — user already exists.
  • 429 — 3 signups per IP per hour.
  • 500 — credentials file or pickup directory I/O failure.

Example (complete signup flow)

# 1) Fetch captcha + read the question to the user
$ CAP=$(curl -s https://phone.codeb.io/captcha.ashx)
$ TOK=$(echo "$CAP" | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")

# 2) Hash the password in the browser (or here, locally; never send plaintext)
#    HA1 = MD5(user:realm:password). The realm for phone.codeb.io is "phone.codeb.io".
$ HA1=$(printf 'alex:phone.codeb.io:s3cret-pw!' | md5sum | awk '{print $1}')

# 3) POST the signup
$ curl -X POST https://phone.codeb.io/signup.ashx \
    --data-urlencode "user=alex" \
    --data-urlencode "name=Alex Example" \
    --data-urlencode "email=alex@example.com" \
    --data-urlencode "ha1=$HA1" \
    --data-urlencode "captcha_token=$TOK" \
    --data-urlencode "captcha_answer=<the integer the user typed>"
{"ok":true,"user":"alex"}

# 4) An activation email lands in the user's inbox; clicking the link
#    hits /activate.ashx?token=<one-time> and flips disabled=false.
Plaintext passwords never reach the server — the browser hashes user:realm:password to an HA1 before transmission, identical to the SIP digest scheme used by the rest of the platform. The activation token has a 7-day TTL.
Need an admin endpoint? Admin-only and OIDC Bearer-gated routes are documented inside the admin UI itself (visible only to signed-in admins on this host). The public API set on this page is the surface you can integrate against without provisioning a CodeB user.

Questions? Ask us · Index: All public APIs