propgate docs

API reference › AccountsSign up

Start a signup

POST/v1/signuppropgate signup

The only unauthenticated route that writes to the database, besides its own confirm step — there is no key to present yet, so the mailbox is the credential. Sends a six-digit code to the address given, valid for ten minutes and single-use.

FieldTypeDescription
email*stringThe address to send the code to. Lowercased and trimmed before storage, so `A@b.com` and `a@b.com` are one account.
curl -s -X POST https://api.propgate.dev/v1/signup \
  -H "content-type: application/json" \
  -d '{"email":"you@example.com"}'
{
  "data": {
    "object": "signup",
    "status": "pending"
  },
  "error": null,
  "meta": null
}

The response is identical whether or not the address already has an account. That reads like a missing feature until you know why: a signup endpoint that answers already registered tells whoever holds a leaked address list which of those addresses use us. Running this again on an address that already has one mints an additional key against the same account rather than a second account — that is also the recovery path if you lose a key, which is why there is no separate sign-in.

Next, exchange the code with POST /v1/signup/confirm.

Failure modes

A malformed body is a 422, in the same field: message shape used throughout the API:

{
  "data": null,
  "error": {
    "message": "email: Invalid input: expected string, received undefined"
  },
  "meta": null
}
{
  "data": null,
  "error": {
    "message": "email: Too small: expected string to have >=3 characters"
  },
  "meta": null
}

Signup and confirm share a limiter of twenty requests per client address per hour — the tripwire against turning this into a spam relay against our own sending reputation. A 429 names the wait and sets Retry-After:

{
  "data": null,
  "error": {
    "message": "too many signup requests; try again in 2117s"
  },
  "meta": null
}