Authentication¶
All protected routes expect:
Tokens are issued by POST /auth/register and POST /auth/login. The JWT module uses expiresIn: '7d' for normal access tokens unless noted otherwise.
Token storage
Store accessToken securely (secret manager, encrypted session, mobile secure storage). The API does not implement refresh tokens in the snippets below; re-login when expired.
Error envelope¶
Most errors from Nest HttpException paths use:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR | UNAUTHORIZED | FORBIDDEN | NOT_FOUND | CONFLICT | INTERNAL_ERROR",
"message": "Human-readable message",
"details": []
}
}
code maps from HTTP status (see HttpExceptionFilter in apps/api). details may list validation messages when message was an array.
Login failure is special: invalid credentials return HTTP 200 with:
Check both status and success when handling login responses.
Register¶
POST /auth/register — Public. Body: email, password, optional name, optional referralCode.
Replace https://api.azscraper.com with your own deployment's base URL if self-hosting.
const res = await fetch("https://api.azscraper.com/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: "dev@example.com",
password: "SecurePassw0rd!",
name: "Dev User",
}),
});
const body = await res.json();
if (!res.ok) console.error(body);
else console.log(body.accessToken, body.user);
Success (example)
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": "67c...f1", "email": "dev@example.com", "name": "Dev User" }
}
Error (duplicate email, HTTP 409)
{
"success": false,
"error": {
"code": "CONFLICT",
"message": "An account with this email already exists",
"details": []
}
}
Login¶
POST /auth/login — Public.
const res = await fetch("https://api.azscraper.com/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: "dev@example.com",
password: "SecurePassw0rd!",
}),
});
const body = await res.json();
if (body.success === false) {
console.error(body.error);
} else {
console.log(body.accessToken);
}
Success
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": "67c...f1", "email": "dev@example.com", "name": "Dev User" }
}
Invalid credentials (HTTP 200, check success)
Logout¶
POST /auth/logout — Returns 204 No Content. No JWT guard on the route (logout is a client-side convention); discard accessToken locally.
Handoff (optional)¶
Used for short-lived exchange flows (e.g. cross-app handoff).
| Endpoint | Purpose |
|---|---|
POST /auth/login-handoff |
Body: email, password. Returns handoffToken (JWT expiresIn: '5m') plus user. |
POST /auth/verify-handoff |
Body: { "handoffToken": "..." }. Returns a normal accessToken + user. |
Invalid handoff yields 401 with the standard error envelope.
Related¶
- Get started — base URL and flow.
- Get data — authenticated project and job APIs.