Files
FlockPal/docs/API_REFERENCE.md
T
Corey Blais d5bb87910e
Deploy / deploy-dev (push) Successful in 2m31s
Deploy / deploy-prod (push) Has been skipped
Added adoption report and transfer code
2026-06-01 18:57:53 -04:00

1269 lines
26 KiB
Markdown

# FlockPal API Reference
This document describes the HTTP API currently implemented in `backend/src/app.ts`.
## Base URLs
- Development frontend: `http://localhost:3000`
- Development API: `http://localhost:5000`
- Production API: use your configured `BACKEND_URL`
## Authentication
Most protected endpoints use a bearer token:
```http
Authorization: Bearer <token>
```
The current backend supports two token systems.
### 1. Browser session tokens
Browser session tokens are created after:
- a successful magic-link sign-in
- a successful OAuth sign-in with Google, Microsoft, or Apple
After sign-in, the backend redirects the browser back to the frontend with an `auth_token` query parameter. That `auth_token` is the browser session token.
Example redirect:
```text
http://localhost:3000/?auth_token=YOUR_SESSION_TOKEN
```
The backend stores only a hash of the session token in the database. The raw token is returned to the client once when the session is created.
### 2. Integration tokens
Integration tokens are created by an authenticated browser-session user through:
- `GET /api/integration-tokens`
- `POST /api/integration-tokens`
- `DELETE /api/integration-tokens/:tokenId`
These tokens are intended for automation tools such as n8n, scripts, and server-to-server use.
Integration tokens are:
- workspace-scoped
- tied to the creating user
- returned in raw form only once at creation time
- either `read_only` or `read_write`
Use them exactly like session tokens:
```http
Authorization: Bearer flpt_...
```
### Token behavior by endpoint type
Browser-session-only endpoints:
- `/api/auth/logout`
- `/api/auth/session`
- `/api/auth/switch-workspace`
- `/api/workspaces`
- `/api/integration-tokens`
Endpoints that accept either browser session tokens or integration tokens:
- `/api/workspace`
- `/api/workspace/members`
- `/api/birds`
- `/api/birds/:birdId/weights`
- `/api/birds/:birdId/vet-visits`
- `/api/birds/:birdId/medications`
Read-only integration tokens can call read endpoints, but cannot call write endpoints.
If authentication is missing or invalid, the API returns:
```json
{ "error": "Authentication required." }
```
Browser-session-only endpoints reject integration tokens with:
```json
{
"error": "This endpoint requires a browser session instead of an integration token."
}
```
Write endpoints reject read-only integration tokens with:
```json
{
"error": "That integration token is read-only."
}
```
## How Browser `auth_token` Is Issued
FlockPal issues the browser bearer token on the backend after a successful passwordless sign-in. The client does not generate it.
### Magic-link flow
1. The client calls `POST /api/auth/magic-link/request`.
2. The backend creates a short-lived magic-link token and emails it, or returns a preview URL in local development.
3. The user opens the magic link.
4. `GET /api/auth/magic-link/verify` validates the magic-link token, creates an auth session, and generates a new `auth_token`.
5. The backend redirects to the frontend with `auth_token` in the query string.
Example redirect:
```text
http://localhost:3000/?auth_token=YOUR_SESSION_TOKEN
```
### OAuth flow
1. The client sends the user to `GET /api/auth/oauth/{provider}/start`.
2. The provider authenticates the user and redirects back to the backend callback.
3. The backend callback creates an auth session and generates a new `auth_token`.
4. The backend redirects to the frontend with `auth_token` in the query string.
Example redirect:
```text
http://localhost:3000/?auth_token=YOUR_SESSION_TOKEN
```
### How the browser token is used
After the frontend receives `auth_token`, it should store it and send it on authenticated requests:
```http
Authorization: Bearer YOUR_SESSION_TOKEN
```
Integration tokens use the same bearer-token header format, but they are created separately and are not used for browser login.
## Roles
Workspace roles used by protected endpoints:
- `owner`
- `assistant`
- `caregiver`
- `viewer`
Role requirements are called out per endpoint below. If the signed-in member lacks permission, the API returns:
```json
{ "error": "You do not have permission for that action." }
```
## Data Shapes
### User
```json
{
"id": "uuid",
"email": "person@example.com",
"name": "Taylor",
"createdAt": "2026-04-14T12:34:56.000Z"
}
```
### Workspace
```json
{
"id": 1001,
"name": "Home Flock",
"workspaceType": "standard",
"billingEmail": "billing@example.com",
"billingPlan": "household_basic",
"createdAt": "2026-04-14T12:34:56.000Z",
"updatedAt": "2026-04-14T12:34:56.000Z"
}
```
### Workspace Member
```json
{
"id": "uuid",
"workspaceId": 1001,
"userId": "uuid",
"inviteEmail": "member@example.com",
"name": "Alex",
"role": "viewer",
"acceptedAt": "2026-04-14T12:34:56.000Z",
"createdAt": "2026-04-14T12:34:56.000Z"
}
```
### Bird
```json
{
"id": "uuid",
"workspaceId": 1001,
"name": "Kiwi",
"tagId": "FP-001",
"species": "Cockatiel",
"vetClinicName": "Avian Care Center",
"vetClinicAddress": "123 Feather Lane, Raleigh, NC",
"vetAccountNumber": "FP-1001",
"vetDoctorName": "Dr. Rivera",
"gender": "female",
"dateOfBirth": "2023-05-10",
"gotchaDay": "2023-08-21",
"chartColor": "#cb3a35",
"photoDataUrl": null,
"notifyOnDob": false,
"notifyOnGotchaDay": true,
"createdAt": "2026-04-14T12:34:56.000Z",
"latestWeightGrams": 92,
"latestRecordedOn": "2026-04-14"
}
```
### Weight
```json
{
"id": "uuid",
"birdId": "uuid",
"weightGrams": 92,
"recordedOn": "2026-04-14",
"notes": "Morning check"
}
```
### Vet Visit
```json
{
"id": "uuid",
"birdId": "uuid",
"visitedOn": "2026-04-14",
"clinicName": "Avian Care Center",
"reason": "Wellness exam",
"notes": "Healthy"
}
```
### Medication
```json
{
"id": "uuid",
"birdId": "uuid",
"name": "Meloxicam",
"dosage": "0.05 mL",
"frequency": "twice_daily",
"doseSchedule": [
{
"key": "dose-1",
"label": "Morning",
"time": "08:00"
},
{
"key": "dose-2",
"label": "Evening",
"time": "20:00"
}
],
"route": "Oral",
"startDate": "2026-04-14",
"endDate": null,
"notes": "Give with food"
}
```
### Medication Administration
```json
{
"id": "uuid",
"medicationId": "uuid",
"birdId": "uuid",
"administeredOn": "2026-04-14",
"administrationSlot": "dose-1",
"status": "administered",
"notes": null,
"createdByUserId": "uuid",
"createdAt": "2026-04-14T12:34:56.000Z"
}
```
## Common Validation Rules
- Dates use `YYYY-MM-DD`
- `workspaceType` is `standard` or `rescue`
- member `role` is `owner`, `assistant`, `caregiver`, or `viewer`
- bird `gender` is `unknown`, `male`, or `female`
- bird `chartColor` must be a `#RRGGBB` hex color
- `photoDataUrl` must be a base64 `data:image/...` URL
- `weightGrams` must be a positive number up to `10000`
Validation failures return `400` with this shape:
```json
{
"error": "Invalid ... payload",
"details": {}
}
```
## Endpoints
### Health
#### `GET /api/health`
Public health check.
Response `200`:
```json
{ "ok": true }
```
### Metrics
#### `GET /api/metrics`
Requires auth and an admin user. Returns lightweight in-memory process and request counters for the current backend process.
Response `200`:
```json
{
"startedAt": "2026-05-01T00:00:00.000Z",
"uptimeSeconds": 120,
"requests": {
"total": 10,
"inFlight": 0,
"errors": 0,
"averageDurationMs": 12.5,
"byStatus": { "2xx": 10 },
"byRoute": { "GET /api/health": 10 }
},
"memory": {
"rss": 0,
"heapTotal": 0,
"heapUsed": 0,
"external": 0,
"arrayBuffers": 0
},
"queues": {
"birdMilestoneReminders": {
"waiting": 0,
"active": 0,
"delayed": 0,
"completed": 0,
"failed": 0
}
}
}
```
### Admin
#### `PATCH /api/admin/rescue-workspaces/:workspaceId`
Requires an admin user. Browser session tokens and admin-owned `read_write` integration tokens are accepted, so automation tools can approve or reject rescue claims after external validation.
Request body:
```json
{
"rescueVerificationStatus": "approved"
}
```
Allowed statuses are `pending`, `approved`, and `rejected`.
### Authentication
#### `GET /api/auth/providers`
Public list of configured OAuth providers.
Response `200`:
```json
{
"providers": [
{
"providerKey": "google",
"displayName": "Google",
"enabled": true
}
]
}
```
#### `POST /api/auth/register`
Password registration is disabled.
Response `410`:
```json
{
"error": "Password-based registration is disabled. Use a magic link or an identity provider."
}
```
#### `POST /api/auth/login`
Password sign-in is disabled.
Response `410`:
```json
{
"error": "Password-based sign-in is disabled. Use a magic link or an identity provider."
}
```
#### `POST /api/auth/magic-link/request`
Starts a passwordless sign-in flow.
Request body:
```json
{
"email": "person@example.com",
"name": "Taylor",
"redirectTo": "http://localhost:3000"
}
```
Notes:
- `name` is optional
- `redirectTo` is optional and defaults to the frontend base URL
- if email delivery is not configured, the API returns a preview URL instead
Response `202`:
```json
{
"ok": true,
"message": "If that address can sign in, a magic link is on the way.",
"previewUrl": "http://localhost:5000/api/auth/magic-link/verify?token=...",
"delivery": "preview"
}
```
`curl` example:
```bash
curl -X POST http://localhost:5000/api/auth/magic-link/request \
-H 'Content-Type: application/json' \
-d '{
"email": "person@example.com",
"name": "Taylor",
"redirectTo": "http://localhost:3000"
}'
```
Local-development example response when SMTP is not configured:
```json
{
"ok": true,
"message": "If that address can sign in, a magic link is on the way.",
"previewUrl": "http://localhost:5000/api/auth/magic-link/verify?token=...",
"delivery": "preview"
}
```
#### `GET /api/auth/magic-link/verify?token=...`
Consumes a single-use magic-link token, creates or loads the user, creates a session, and redirects to the frontend with `auth_token` in the query string.
Responses:
- `302` redirect on success
- `400` if the token is missing, invalid, or expired
If you are testing locally and received a `previewUrl`, open that URL in a browser or inspect the redirect target to capture the `auth_token`.
#### `POST /api/auth/logout`
Requires a browser session. Invalidates the current session.
Response `204` with no body.
#### `GET /api/auth/session`
Requires a browser session. Returns the current session context.
Response `200`:
```json
{
"token": "raw-session-token",
"session": {
"user": {
"id": "uuid",
"email": "person@example.com",
"name": "Taylor",
"createdAt": "2026-04-14T12:34:56.000Z"
},
"activeWorkspace": {
"id": 1001,
"name": "Home Flock",
"workspaceType": "standard",
"billingEmail": null,
"billingPlan": "household_basic",
"createdAt": "2026-04-14T12:34:56.000Z",
"updatedAt": "2026-04-14T12:34:56.000Z"
},
"activeMembership": {
"id": "uuid",
"workspaceId": 1001,
"userId": "uuid",
"inviteEmail": "person@example.com",
"name": "Taylor",
"role": "owner",
"acceptedAt": "2026-04-14T12:34:56.000Z",
"createdAt": "2026-04-14T12:34:56.000Z"
},
"workspaces": [],
"providers": []
}
}
```
`curl` example:
```bash
curl http://localhost:5000/api/auth/session \
-H 'Authorization: Bearer YOUR_SESSION_TOKEN'
```
#### `POST /api/auth/switch-workspace`
Requires a browser session. Switches the session's active workspace.
Request body:
```json
{
"workspaceId": 1002
}
```
Response `200` returns the same shape as `GET /api/auth/session`.
`curl` example:
```bash
curl -X POST http://localhost:5000/api/auth/switch-workspace \
-H 'Authorization: Bearer YOUR_SESSION_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"workspaceId": 1002
}'
```
Possible errors:
- `403` if the user is not a member of the requested workspace
#### `GET /api/auth/oauth/{provider}/start`
Starts an OAuth login flow and redirects to the external identity provider.
Path params:
- `provider`: `google`, `microsoft`, or `apple`
Concrete examples:
- `/api/auth/oauth/google/start`
- `/api/auth/oauth/microsoft/start`
- `/api/auth/oauth/apple/start`
Query params:
- `redirectTo` optional frontend redirect target after successful login
Responses:
- `302` redirect to provider on success
- `404` for an unknown provider
- `400` if the provider is not configured
Browser-oriented example:
```text
http://localhost:5000/api/auth/oauth/google/start?redirectTo=http://localhost:3000
```
`curl` can show the initial redirect, but this flow is meant to complete in a browser:
```bash
curl -i "http://localhost:5000/api/auth/oauth/google/start?redirectTo=http://localhost:3000"
```
#### `GET /api/auth/oauth/{provider}/callback`
#### `POST /api/auth/oauth/{provider}/callback`
OAuth callback used by providers. On success, the backend redirects to the frontend with `auth_token` in the query string.
Path params:
- `provider`: `google`, `microsoft`, or `apple`
Responses:
- `302` redirect on success
- `400` for missing or expired OAuth state
- `404` for unknown provider
### Workspaces
#### `GET /api/workspaces`
Requires a browser session. Lists the signed-in user's workspace memberships.
Response `200`:
```json
{
"workspaces": []
}
```
#### `POST /api/workspaces`
Requires a browser session. Creates a new workspace and makes the current user its `owner`.
Request body:
```json
{
"name": "Home Flock",
"workspaceType": "standard",
"billingEmail": "billing@example.com",
"billingPlan": "household_plus"
}
```
Notes:
- `workspaceType` must be `standard` or `rescue`
- `billingPlan` may be `household_basic`, `household_plus`, `household_macaw`, or `household_hyacinth_macaw`
- rescue workspaces are forced to `rescue_free`
Response `201`:
```json
{
"workspace": {}
}
```
#### `GET /api/workspace`
Requires auth. Returns the active workspace. Browser sessions and integration tokens can both use this endpoint.
Response `200`:
```json
{
"workspace": {}
}
```
#### `PUT /api/workspace`
Requires auth with write access and role `owner` or `assistant`. Updates the active workspace.
Request body:
```json
{
"name": "Updated Flock",
"workspaceType": "standard",
"billingEmail": "billing@example.com",
"billingPlan": "household_basic"
}
```
Response `200`:
```json
{
"workspace": {}
}
```
#### `DELETE /api/workspace`
Requires a browser session and role `owner`. Deletes the active flock only when it has no birds.
Behavior:
- if the flock still has birds, deletion is blocked
- collaborators, sessions, and integration tokens tied to the flock are removed with it
- the backend switches the user to another existing flock, or creates a new personal flock automatically if needed
Response `200`:
```json
{
"deletedWorkspaceId": 1001,
"token": "raw-session-token",
"session": {}
}
```
Possible errors:
- `409` if birds are still assigned to the flock
- `404` if the flock no longer exists
#### `GET /api/workspace/members`
Requires auth. Lists members for the active workspace. Browser sessions and integration tokens can both use this endpoint.
Response `200`:
```json
{
"members": []
}
```
#### `POST /api/workspace/members`
Requires auth with write access and role `owner` or `assistant`. Invites or upserts a workspace member.
Request body:
```json
{
"name": "Alex",
"email": "alex@example.com",
"role": "viewer"
}
```
Response `201`:
```json
{
"member": {}
}
```
#### `DELETE /api/workspace/members/:memberId`
Requires auth with write access and role `owner` or `assistant`. Removes a non-owner member.
Response `204` with no body.
Possible errors:
- `404` if the member was not found or is an owner
### Birds
#### `GET /api/birds`
Requires auth. Lists birds in the active workspace. Browser sessions and integration tokens can both use this endpoint.
Response `200`:
```json
{
"birds": []
}
```
#### `POST /api/birds`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Creates a bird.
Request body:
```json
{
"name": "Kiwi",
"tagId": "FP-001",
"species": "Cockatiel",
"vetClinicName": "Avian Care Center",
"vetClinicAddress": "123 Feather Lane, Raleigh, NC",
"vetAccountNumber": "FP-1001",
"vetDoctorName": "Dr. Rivera",
"gender": "female",
"dateOfBirth": "2023-05-10",
"gotchaDay": "2023-08-21",
"chartColor": "#cb3a35",
"photoDataUrl": "",
"notifyOnDob": false,
"notifyOnGotchaDay": true
}
```
Notes:
- `dateOfBirth`, `gotchaDay`, `photoDataUrl`, and veterinary info fields may be omitted or sent as empty strings
- `chartColor` defaults to `#cb3a35`
Response `201`:
```json
{
"bird": {}
}
```
Possible errors:
- `409` if the workspace already uses that `tagId`
#### `PUT /api/birds/:birdId`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Updates a bird.
Request body matches `POST /api/birds`.
Response `200`:
```json
{
"bird": {}
}
```
Possible errors:
- `404` if the bird does not exist in the active workspace
- `409` if the workspace already uses that `tagId`
#### `POST /api/birds/:birdId/transfer`
Requires a browser session, write access, and role `owner` or `assistant`. Transfers a bird from the active flock to a flock owned by the provided receiving owner email. The sender does not need access to the receiving flock.
Request body:
```json
{
"destinationOwnerEmail": "new-owner@example.com"
}
```
Notes:
- if the receiving owner email does not currently own a receiving flock, FlockPal creates a pending transfer, sends a bird-transfer invite, and returns `202`; the bird stays in the sender's flock until the recipient signs in
- pending transfers auto-complete when the recipient signs in; FlockPal creates or uses the recipient's personal flock as the receiving flock
- immediate transfer requires the receiving owner email to match an accepted `owner` of exactly one other flock
- when transferred, the bird keeps its existing weight and vet history because the record itself is reassigned
Response `200`:
```json
{
"bird": {},
"destinationOwnerEmail": "new-owner@example.com",
"destinationWorkspace": {}
}
```
Response `202` when the receiving email does not currently own a receiving flock:
```json
{
"ok": true,
"bird": {},
"destinationOwnerEmail": "new-owner@example.com",
"inviteSent": true,
"invitePreviewUrl": "http://localhost:5000/api/auth/magic-link/verify?token=...",
"inviteDelivery": "preview",
"message": "A bird transfer invite was sent. The bird will stay in this flock until the recipient signs in, then FlockPal will automatically move it to their receiving flock."
}
```
Possible errors:
- `400` if the payload is invalid
- `404` if the bird is not in the active flock
- `409` if that owner email owns more than one receiving flock
- `409` if the destination flock already has a bird using the same `tagId`
#### `POST /api/birds/:birdId/transfer-code`
Requires a browser session, write access, and role `owner` or `assistant`. Creates a unique transfer code for a bird. Creating a new open code for the same bird revokes earlier unused codes for that bird.
Response `201`:
```json
{
"transferCode": {
"code": "secure-code",
"bird": {}
}
}
```
#### `POST /api/bird-transfer-codes/:code/accept`
Requires a browser session, write access, and role `owner` or `assistant`. Accepts a transfer code into the signed-in user's active flock.
Response `200`:
```json
{
"bird": {},
"sourceWorkspaceName": "Previous Flock",
"workspace": {}
}
```
Possible errors:
- `404` if the code does not exist, was revoked, was already used, or the bird is no longer available
- `409` if the bird is already in the active flock or the active flock already has the same `tagId`
#### `DELETE /api/birds/:birdId`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Deletes a bird.
Response `204` with no body.
Possible errors:
- `404` if the bird does not exist in the active workspace
### Weights
#### `GET /api/birds/:birdId/weights`
Requires auth. Lists weight entries for a bird in the active workspace.
Query params:
- `days` optional, clamped to `1` through `425`, default `30`
Response `200`:
```json
{
"weights": []
}
```
#### `POST /api/birds/:birdId/weights`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Creates a weight entry.
Request body:
```json
{
"weightGrams": 92,
"recordedOn": "2026-04-14",
"notes": "Morning check"
}
```
Response `201`:
```json
{
"weight": {}
}
```
Possible errors:
- `404` if the bird does not exist in the active workspace
- `409` if a weight already exists for that bird on that date
### Vet Visits
#### `GET /api/birds/:birdId/vet-visits`
Requires auth. Lists vet visits for a bird in the active workspace.
Response `200`:
```json
{
"vetVisits": []
}
```
#### `POST /api/birds/:birdId/vet-visits`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Creates a vet visit.
Request body:
```json
{
"visitedOn": "2026-04-14",
"clinicName": "Avian Care Center",
"reason": "Wellness exam",
"notes": "Healthy"
}
```
Response `201`:
```json
{
"vetVisit": {}
}
```
Possible errors:
- `404` if the bird does not exist in the active workspace
### Medications
#### `GET /api/birds/:birdId/medications`
Requires auth. Lists medication records for a bird in the active workspace.
Response `200`:
```json
{
"medications": []
}
```
#### `POST /api/birds/:birdId/medications`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Creates a medication record.
Request body:
```json
{
"name": "Meloxicam",
"dosage": "0.05 mL",
"frequency": "twice_daily",
"doseSchedule": [
{
"key": "dose-1",
"label": "Morning",
"time": "08:00"
},
{
"key": "dose-2",
"label": "Evening",
"time": "20:00"
}
],
"route": "Oral",
"startDate": "2026-04-14",
"endDate": "",
"notes": "Give with food"
}
```
Response `201`:
```json
{
"medication": {}
}
```
#### `PUT /api/birds/:birdId/medications/:medicationId`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Updates a medication record.
#### `DELETE /api/birds/:birdId/medications/:medicationId`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Deletes a medication record.
#### `GET /api/birds/:birdId/medication-administrations`
Requires auth. Lists medication administration events for a bird in the active workspace.
Response `200`:
```json
{
"administrations": []
}
```
#### `POST /api/birds/:birdId/medications/:medicationId/administrations`
Requires auth with write access and role `owner`, `assistant`, or `caregiver`. Upserts one scheduled medication event for a date and interval slot.
Request body:
```json
{
"administeredOn": "2026-04-14",
"administrationSlot": "dose-1",
"status": "administered",
"notes": ""
}
```
`status` is `administered` or `missed`. `administrationSlot` identifies the interval event for that day, such as `dose-1` or `dose-2`.
Medication `frequency` is one of `once_daily`, `twice_daily`, `every_8_hours`, `every_6_hours`, or `as_needed`. `doseSchedule` stores the editable labels and optional 24-hour `HH:MM` times used by administration slots.
Possible errors:
- `400` if `endDate` is before `startDate`
- `404` if the bird or medication does not exist in the active workspace
### Integration Tokens
These endpoints are for browser-session users managing their own automation tokens. They are not accessible with an integration token itself.
#### `GET /api/integration-tokens`
Requires a browser session. Lists the current user's active integration tokens for the active workspace.
Response `200`:
```json
{
"integrationTokens": [
{
"id": "uuid",
"userId": "uuid",
"workspaceId": 1001,
"name": "n8n household sync",
"tokenPrefix": "flpt_1234abcd56",
"scope": "read_write",
"lastUsedAt": "2026-04-14T12:34:56.000Z",
"expiresAt": null,
"revokedAt": null,
"createdAt": "2026-04-14T12:00:00.000Z"
}
]
}
```
#### `POST /api/integration-tokens`
Requires a browser session. Creates a new integration token for the active workspace and returns the raw token once.
Request body:
```json
{
"name": "n8n household sync",
"scope": "read_write",
"expiresInDays": 90
}
```
Notes:
- `scope` may be `read_only` or `read_write`
- `expiresInDays` is optional
- the raw token is only returned at creation time
Response `201`:
```json
{
"integrationToken": {
"id": "uuid",
"userId": "uuid",
"workspaceId": 1001,
"name": "n8n household sync",
"tokenPrefix": "flpt_1234abcd56",
"scope": "read_write",
"lastUsedAt": null,
"expiresAt": "2026-07-13T12:00:00.000Z",
"revokedAt": null,
"createdAt": "2026-04-14T12:00:00.000Z"
},
"token": "flpt_..."
}
```
`curl` example:
```bash
curl -X POST http://localhost:5000/api/integration-tokens \
-H 'Authorization: Bearer YOUR_SESSION_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "n8n household sync",
"scope": "read_write",
"expiresInDays": 90
}'
```
Use the returned token in your automation tool:
```http
Authorization: Bearer flpt_...
```
#### `DELETE /api/integration-tokens/:tokenId`
Requires a browser session. Revokes an integration token owned by the current user in the active workspace.
Response `204` with no body.
## Error Summary
Common status codes used by the API:
- `200` successful read or update
- `201` resource created
- `202` async or queued success for magic-link requests
- `204` successful delete or logout with no response body
- `400` invalid request payload or expired callback state
- `401` authentication required
- `403` authenticated but not authorized for the action
- `404` resource or provider not found
- `409` uniqueness conflict
- `410` password-based auth endpoints intentionally disabled
## Source of Truth
This document reflects the routes currently implemented in:
- `backend/src/app.ts`
If the docs and code ever disagree, treat the code as the source of truth.
## Quick `curl` Workflow
Basic local-development auth check:
1. Request a magic link:
```bash
curl -X POST http://localhost:5000/api/auth/magic-link/request \
-H 'Content-Type: application/json' \
-d '{
"email": "person@example.com",
"name": "Taylor",
"redirectTo": "http://localhost:3000"
}'
```
2. Copy the `previewUrl` from the response if local email is not configured.
3. Open that URL in a browser and capture `auth_token` from the frontend redirect URL.
4. Use the token:
```bash
curl http://localhost:5000/api/auth/session \
-H 'Authorization: Bearer YOUR_SESSION_TOKEN'
```