Backend API Reference
REST API for workspace, project, model, chat, billing, and notification operations. Authenticate with an access token.
Backend API Reference
Base URL: https://app.nfyio.com/api
The backend API is a JSON REST surface. Authenticate every request with an access token:
curl https://app.nfyio.com/api/auth/me \
-H "Authorization: Bearer $NFYIO_ACCESS_TOKEN"
S3 bucket and object operations (upload, download, list, multipart, presigned URLs) are not on this surface. Use the Object Storage endpoint instead.
Conventions
- Identifiers are UUIDs called
uid, returned as strings. - Timestamps are ISO 8601 in UTC:
2026-05-04T12:34:56.000Z. - Pagination is
?page=1&limit=50where supported. Responses includepagination: { page, limit, total, totalPages }. - Filtering uses query parameters when documented per endpoint.
Standard envelope
Every response uses:
{
"success": true,
"data": { /* … */ }
}
or, on error:
{
"success": false,
"error": { "code": "STRING", "message": "human readable", "details": "optional" }
}
Common error codes
| Code | HTTP | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing / invalid / expired token |
ROUTE_FORBIDDEN | 403 | Access token’s route restriction blocks this path |
MISSING_CONTEXT | 400 | Workspace / project context could not be resolved for the token |
NOT_FOUND | 404 | Resource does not exist or is in another workspace |
INVALID_INPUT | 400 | Body or query parameters failed validation |
DUPLICATE_ENTRY | 409 | Unique constraint violation |
QUOTA_EXCEEDED | 402 | Plan limit hit; check /billing/quota |
INTERNAL_ERROR | 500 | Unhandled server error — retry, then contact support |
Auth
GET /auth/me
Returns the user, workspace, project, and active team for the calling token.
curl https://app.nfyio.com/api/auth/me \
-H "Authorization: Bearer $TOKEN"
{
"success": true,
"data": {
"user": { "id": "kc-sub", "email": "...", "firstName": "Ada", "lastName": "Lovelace" },
"workspaceId": "ws-uid",
"projectId": "prj-uid",
"selectedTeam": { "uid": "team-uid", "name": "Default" },
"billingAccountUid": "ba-uid",
"plan": { "name": "Pro", "type": "paid", "category": "standard" }
}
}
PATCH /auth/profile
Update the calling user’s first/last name.
Body: { "firstName": "Ada", "lastName": "Lovelace" }. Returns the new values.
Workspaces
| Method | Path | Purpose |
|---|---|---|
| GET | /workspaces | List workspaces the user belongs to |
| POST | /workspaces | Create a new workspace |
| GET | /workspaces/:uid | Workspace detail |
| PUT | /workspaces/:uid | Update workspace |
| DELETE | /workspaces/:uid | Delete workspace (irreversible) |
Projects
| Method | Path | Purpose |
|---|---|---|
| GET | /projects | List projects in the active workspace |
| POST | /projects | Create a project |
| POST | /projects/select | Switch the session’s active project. Body: { "projectUid": "…" } |
| GET / PUT / DELETE | /projects/:uid | Read / update / delete |
Teams
| Method | Path | Purpose |
|---|---|---|
| GET | /teams | List teams in the workspace |
| POST | /teams | Create a team |
| POST | /teams/switch | Switch the active team in the session |
| GET / PUT / DELETE | /teams/:uid | Read / update / delete |
Members & invites
| Method | Path | Purpose |
|---|---|---|
| GET | /team-members?teamUid=… | List members of a team |
| POST | /team-members | Add a member directly |
| POST | /team-members/invite | Email an invite. Body: { email, teamUid, role: "modifier"|"viewer" } |
| GET / PUT / DELETE | /team-members/:uid | Read / change role / remove |
| GET | /invites | List pending invites for the calling user |
| GET | /invites/:id | Invite detail |
| POST | /invites/:id/accept | Accept an invite |
| POST | /invites/:id/reject | Reject an invite |
Buckets (settings only)
These endpoints manage bucket records — naming, project assignment, RAG / embedding configuration, versioning, and lifecycle. They do not upload, download, list or delete objects. For that, use the S3 endpoint described in Object Storage.
| Method | Path | Purpose |
|---|---|---|
| GET | /object-storage/buckets/check-name?name=… | Returns { available: true|false } |
| GET | /object-storage/buckets?page&limit&search | List buckets in active workspace |
| POST | /object-storage/buckets | Create a bucket. Body fields: name, region, projectUid, useReason ("hot"|"cold"), storageType ("standard"|"pro"|"cold"|"zip"), isEmbeddingsEnabled, embeddingModelUid, llmModelUid, embeddingApiKey, llmApiKey, isCDN. Returns { jobId } — poll with /object-storage/jobs/:jobId. |
| GET | /object-storage/buckets/:bucketName | Bucket detail (settings + indexing status) |
| PUT | /object-storage/buckets | Update settings. Body must include current bucketName plus fields to change. |
| PUT | /object-storage/buckets/:bucketName/versioning | Enable / disable object versioning. Body: { enabled: true|false } |
| DELETE | /object-storage/buckets | Soft-delete a bucket. Body: { bucketName }. Returns { jobId }. |
Object metadata listing (no payload)
For convenience, the backend can return object metadata without going through the S3 endpoint. These are read-only and meant for dashboards / pickers — large transfers should still go through S3.
| Method | Path | Purpose |
|---|---|---|
| GET | /object-storage/buckets/:bucketName/objects?prefix&page&limit | List object keys + sizes + index status |
| GET | /object-storage/buckets/:bucketName/objects/:key+ | Object metadata (size, type, indexed-at) |
| GET | /object-storage/buckets/:bucketName/objects/:key+/content | Stream object bytes (small reads only — prefer S3 GetObject) |
RAG / Embeddings
| Method | Path | Purpose |
|---|---|---|
| GET | /object-storage/buckets/:bucketName/embeddings/status | Indexing progress: { pending, processing, completed, failed } per file |
| GET | /object-storage/buckets/:bucketName/embeddings/usage | Embedding token usage for the bucket |
| GET | /object-storage/buckets/:bucketName/embeddings/search?q=…&limit=…&threshold=… | Semantic search (returns chunk hits with scores) |
| POST | /object-storage/buckets/:bucketName/embeddings/reindex | Reindex every object in the bucket |
| POST | /object-storage/buckets/:bucketName/embeddings/reindex-incomplete | Reindex only pending / failed objects |
| POST | /object-storage/test-embedding-key | Validate a user-provided embedding API key without saving it. Body: { modelUid, apiKey } |
| POST | /object-storage/test-llm-key | Same, for an LLM key |
Models
The platform ships a catalog of LLM and embedding models. Owners can add custom entries.
| Method | Path | Purpose |
|---|---|---|
| GET | /models?group=text|embedding | List models, optionally filtered by group |
| POST | /models | Add a custom model |
| GET / PUT / DELETE | /models/:uid | Read / update / remove |
Chat
| Method | Path | Purpose |
|---|---|---|
| POST | /chat | Send a message. Body: { bucketName, message, conversationId? }. Returns the model reply plus the updated conversation. RAG retrieval against the bucket runs automatically when the bucket has embeddings enabled. |
| GET | /chat/conversations | List the user’s conversations |
| GET | /chat/conversations/:conversationId/messages | Full message history of a conversation |
Notifications
| Method | Path | Purpose |
|---|---|---|
| GET | /notifications?limit&type | List notifications with unread counter |
| POST | /notifications | Create a notification (admin / system flows) |
| PATCH | /notifications/:uid/read | Mark a single notification read |
| POST | /notifications/read-all | Mark every notification read |
| DELETE | /notifications/:uid | Delete a notification |
A WebSocket endpoint at wss://app.nfyio.com/api/ws pushes new notifications in real time when the dashboard is open. Bearer-token clients normally just poll GET /notifications.
Access Tokens
These are the same tokens you mint at Settings → Access Tokens. The endpoints let you manage them programmatically.
| Method | Path | Purpose |
|---|---|---|
| GET | /access-tokens?teamUid=… | List tokens. Token values are NOT returned — only metadata. |
| POST | /access-tokens | Create a token. Body: { scope: "read"|"write", expireDays, description?, route?, teamUid }. Returns the full token value once. |
| GET / PUT / DELETE | /access-tokens/:uid | Read / update / revoke. Revoked tokens stop working on the next request. |
Storage Access Keys (S3 credentials)
Manage the AWS-style key pairs used to talk to https://s3.nfyio.com. The S3 wire protocol itself is documented in Object Storage.
| Method | Path | Purpose |
|---|---|---|
| GET | /object-storage/access-keys?page&limit | List access keys in the workspace |
| GET | /object-storage/access-keys/check-name?name=… | Name availability |
| GET | /object-storage/access-keys/expired | Keys past their expiration date |
| POST | /object-storage/access-keys | Create a key. Body: { name, bucketUids: [...], permission: "read"|"read-write", expiresAt? }. Returns { accessKeyId, secretAccessKey } — secret only once. |
| POST | /object-storage/access-keys/regenerate | Issue a new secret. Body: { uid } |
| PUT | /object-storage/access-keys/permissions | Change permission / bucket scope |
| DELETE | /object-storage/access-keys | Revoke. Body: { uid } |
Firewall
Workspace-level allow / deny rules applied on top of access-token auth.
| Method | Path | Purpose |
|---|---|---|
| GET | /firewall?teamUid=… | List rules |
| POST | /firewall | Create rule. Body: { teamUid, type: "ipv4"|"ipv6"|"hostname", action: "allow"|"deny", ipAddress, description? } |
| GET / PUT / DELETE | /firewall/:uid | Read / update status / delete |
Logs
System-emitted transaction logs. Read-only for tokens; the writeable methods exist for admin tooling and require an admin context.
| Method | Path | Purpose |
|---|---|---|
| GET | /logs?from&to&route&status&page&limit | Tail recent transaction logs |
| GET | /logs/:id | Single log entry |
Dashboard & analytics
| Method | Path | Purpose |
|---|---|---|
| GET | /dashboard?range=7d|30d|90d | KPI rollup + trends + top drivers + bucket preview + quota snapshot. Drives the dashboard view. |
For raw analytics over a custom range:
| Method | Path | Purpose |
|---|---|---|
| GET | /object-storage/analytics/overview?start&end&projectUid | KPI rollup |
| GET | /object-storage/analytics/trends?start&end&projectUid&limit | Daily time-series |
| GET | /object-storage/analytics/top-drivers?start&end&dimension&metric&limit | Top contributors |
| GET | /object-storage/analytics/anomalies?start&end&zScore | Spike detection |
| POST | /object-storage/analytics/refresh | Force-refresh aggregations |
| GET | /object-storage/analytics/refresh/:runId | Refresh job progress |
Billing
Plans, pricing, currencies (read-only)
| Method | Path | Purpose |
|---|---|---|
| GET | /billing/available-plans | Plans the workspace can switch into |
| GET | /billing/plans | All published plans |
| GET | /billing/plans/:uid | Plan detail |
| GET | /billing/pricings | Pricing tiers |
| GET | /billing/pricings/:uid | Pricing detail |
| POST | /billing/pricings/log-view | Track that a pricing card was viewed (UI analytics) |
| GET | /billing/plan-features | Feature catalog |
| GET | /billing/currencies | Supported currencies |
Subscription
| Method | Path | Purpose |
|---|---|---|
| GET | /billing/subscription | Current subscription state |
| POST | /billing/subscription | Subscribe to a plan. Body: { pricingUid, paymentProvider } |
| PUT | /billing/subscription | Upgrade / downgrade |
| DELETE | /billing/subscription | Cancel at period end |
| POST | /billing/subscription/resume | Resume a cancelled subscription before period end |
Payment methods
| Method | Path | Purpose |
|---|---|---|
| GET | /billing/payment-method | Current default payment method |
| POST | /billing/payment-method | Attach a method. Body: { paymentMethodId } (Stripe ID returned by your client SDK) |
| DELETE | /billing/payment-method | Detach |
| POST | /billing/setup-intent | Stripe Setup Intent (returns clientSecret) for use with Stripe Elements |
Usage, quota, transactions
| Method | Path | Purpose |
|---|---|---|
| GET | /billing/quota | Current plan limits + usage. Source-of-truth for the dashboard quota bars. |
| POST | /billing/quota/refresh | Invalidate the workspace’s quota cache and rebuild |
| GET | /billing/usage?month=YYYY-MM | Aggregated billing usage records |
| GET | /billing/usage/:uid | Single usage record |
| GET | /billing/transactions?startDate&endDate&page&limit | Paginated transactions for the usage page |
| GET | /billing/accounts and /billing/accounts/:uid | Billing account profile (address, tax id, etc.) |
Free quota → overage. Stay within the plan limits and usage is free. Once you exceed any metered limit (api calls, embedding tokens, chat tokens, storage GB) the account is billed at the per-unit overage price; on free plans, overage may also pause new operations until you upgrade. Both rules surface as banners on the dashboard.
Feedback
Used by the in-product feedback form.
| Method | Path | Purpose |
|---|---|---|
| POST | /feedbacks | Submit feedback |
| GET | /feedbacks | List user’s submitted feedbacks |
| PATCH | /feedbacks/:uid | Update fields |
| POST | /feedbacks/:uid/complete | Mark resolved |
| DELETE | /feedbacks/:uid | Delete |
Reference catalog
Mostly read-only catalog endpoints used by the dashboard’s pickers. Listed for completeness; treat as GET … / GET …/:uid.
/users,/users/:uid— users in workspace/providers,/providers/:uid— payment / model providers/services,/services/:uid— platform service registry/products,/products/:uid— billable product definitions/product-prices,/product-prices/:uid— pricing rows/networkings,/networkings/:uid— bucket networking config/payments,/payments/:uid— payment records
Each follows the same envelope and CRUD shape as the other resources above.
Rate limits
The backend currently enforces:
- Per-token burst limit:
~100 req / 10 sper access token. - Per-IP global limit:
~600 req / minper source IP.
Exceeding either returns 429 with Retry-After. For high-volume integrations (bulk imports, batch reindexing), batch your operations or contact support to raise the limit.
OpenAPI
The full machine-readable spec is served at:
https://app.nfyio.com/api/docs/openapi.json
Drop it into Postman, Insomnia, or openapi-typescript to generate clients.