Skip to content
einvoicing.dev

API/Sign-in

Get a proof-of-work challenge for sign-in

POST/v1/sign-in-challenges· no key needed

Returns an ALTCHA (v2) proof-of-work challenge. Solve it, then send the result as altcha with POST /v1/sign-ins. With any ALTCHA solver (Go, JavaScript, PHP) it takes well under a second, but it makes sending sign-ins in bulk expensive. It is the headless stand-in for a CAPTCHA.

data is ALTCHA's own format, unchanged, so a solver can take it as it is. That is why its fields are camelCase when the rest of this API is snake_case. If you are writing a solver yourself:

  • Try counter = 0, 1, 2, … For each, derive keyLength bytes with PBKDF2/SHA-256, using cost iterations, salt as the salt, and as the password nonce followed by the counter as a 4-byte big-endian integer. Stop when the derived key starts with keyPrefix.
  • Send base64(JSON {"challenge": <data>, "solution": {"counter": <n>, "derivedKey": "<hex>"}}) as altcha.

Challenges are signed and never stored, so asking for one creates nothing. Each expires at parameters.expiresAt, five minutes after issue, and each can be spent once. Difficulty rises automatically while sign-in volume is unusually high.

Request
curl -X POST https://api.einvoicing.dev/v1/sign-in-challenges

Response

200

A fresh challenge. Never cached, because every challenge is single-use.

FieldTypeDescription
datarequiredSignInChallengeAn ALTCHA v2 proof-of-work challenge, in ALTCHA's own format. Pass it unchanged to an ALTCHA solver.
Example responseapplication/json
{  "data": {    "parameters": {      "algorithm": "PBKDF2/SHA-256",      "cost": 1000,      "expiresAt": 1789135991,      "keyLength": 32,      "keyPrefix": "76daadcb383cfbe788b520e6ef624083",      "keySignature": "2e62b0c7f7033399fd56c0d4f073ec11e575168fa198289e6b89134c92c2756d",      "nonce": "03acffe437ae1e8f7f33ba01bee2d154",      "salt": "fcbaea6dca37599ef2c7e753785b2809"    },    "signature": "e14bccd007302003c6a99fc5f45f016f8f4530df32eb587c3b786bc4bdddd602"  }}

Errors

Every error is application/problem+json (RFC 9457). Branch on type, which is stable, never on title or detail.

StatusWhen
429

Too many requests in a short window. Slow down and retry after the number of seconds in Retry-After. Problem type is rate-limited.

/problems/rate-limited

Schemas

SignInChallenge

An ALTCHA v2 proof-of-work challenge, in ALTCHA's own format. Pass it unchanged to an ALTCHA solver.

FieldTypeDescription
parametersrequiredobjectWhat to solve. Signed as a whole, so changing any field invalidates the challenge.
algorithmrequiredstringThe key derivation function to run for each attempt.

PBKDF2/SHA-256

costrequiredintegerPBKDF2 iterations per attempt.
keyLengthrequiredintegerLength of the derived key, in bytes.
keyPrefixrequiredstringThe derived key must start with these bytes (hex).
keySignaturestringLets the server verify a solution quickly. Opaque to clients; send it back unchanged.
noncerequiredstringHex. Followed by the counter as a 4-byte big-endian integer, it is the PBKDF2 password.
saltrequiredstringHex. The PBKDF2 salt.
expiresAtrequiredintegerUnix time, in seconds, after which the challenge is refused.
signaturerequiredstringThe server's HMAC over parameters. Opaque; send it back unchanged.