Authentication
Two credential types — backend access tokens for the REST API, S3 access keys for object storage. When to use which.
Authentication
nfyio has two separate credential types. They are not interchangeable.
| Credential | Used for | Generated at | Auth scheme |
|---|---|---|---|
Access Token (nfyio_at_…) | Backend REST API at https://app.nfyio.com/api/... | Dashboard → Settings → Access Tokens | HTTP Authorization: Bearer <token> |
| S3 Access Key + Secret | Object storage at https://s3.nfyio.com | Dashboard → Object Storage → Access Keys | AWS Signature v4 (handled by any S3 SDK / CLI) |
The split exists because object storage speaks the AWS S3 wire protocol — every off-the-shelf S3 client expects an access-key/secret pair to sign requests. The backend API is a normal REST surface with bearer auth, so it gets a different credential type.
Access Tokens — backend REST API
Generate
In the dashboard:
- Go to Settings → Access Tokens.
- Click Generate Token.
- Choose:
- Scope —
read(GETs only) orwrite(all methods). - Expiration — number of days (1–365).
- Route restriction (optional) — limit the token to a route prefix, e.g.
/api/chat/*. Requests to other routes return 403.
- Scope —
- Copy the token. The full value (
nfyio_at_…) is shown only once.
Use
Send the token in the Authorization header:
curl https://app.nfyio.com/api/auth/me \
-H "Authorization: Bearer $NFYIO_ACCESS_TOKEN"
fetch('https://app.nfyio.com/api/chat', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.NFYIO_ACCESS_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ bucketName: 'reports', message: 'summarize Q1' })
})
What an access token can do
Anything the calling user can do, restricted by:
- Scope —
readblocks all non-GET methods even if the route allows them. - Route restriction — if set, only requests whose path starts with the allowed prefix are accepted; everything else returns
403 ROUTE_FORBIDDEN. - Workspace context — every token is bound to the workspace it was created in. Switching workspaces in the UI does not affect existing tokens.
- Expiration — tokens stop working after
expireDaysfrom creation.
What an access token cannot do
- Object uploads/downloads. S3 requests at
https://s3.nfyio.comrequire AWS Signature v4 with an access-key/secret pair. Bearer tokens are rejected. - Account-level signin/signup/OTP/password operations. Those are session-cookie flows used by the dashboard and are not exposed to bearer-token clients.
Rotation
Tokens have no built-in rotation. Recommended pattern:
- Generate a new token with the same scope.
- Roll out the new value into your secret store / CI.
- Delete the old token from Settings → Access Tokens.
Deleted tokens stop working immediately on the next call.
S3 Access Keys — object storage
Generate
- Go to Object Storage → Access Keys.
- Click New Access Key.
- Choose:
- Bucket(s) the key may touch.
- Permission —
read(GET / HEAD / List) orread-write(also PUT / DELETE / multipart). - Optional expiration.
- Copy the Access Key ID and Secret Access Key. The secret is shown only once — save it in your secret store before closing the dialog.
Use
Configure any S3-compatible client with the endpoint https://s3.nfyio.com and your key/secret:
aws configure --profile nfyio
# AWS Access Key ID: AKIA…
# AWS Secret Access Key: …
# Default region: us-east-1 (any value, ignored)
aws --profile nfyio --endpoint-url https://s3.nfyio.com \
s3 cp ./file.bin s3://my-bucket/path/file.bin
import boto3
s3 = boto3.client(
's3',
endpoint_url='https://s3.nfyio.com',
aws_access_key_id='AKIA…',
aws_secret_access_key='…',
region_name='us-east-1',
)
s3.upload_file('./file.bin', 'my-bucket', 'path/file.bin')
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
const s3 = new S3Client({
endpoint: 'https://s3.nfyio.com',
region: 'us-east-1',
credentials: { accessKeyId: 'AKIA…', secretAccessKey: '…' },
forcePathStyle: true
})
await s3.send(new PutObjectCommand({ Bucket: 'my-bucket', Key: 'path/file.bin', Body: data }))
What an S3 access key can do
- All S3 bucket and object operations on the buckets it was scoped to.
- See the full list in Object Storage.
What an S3 access key cannot do
- Backend REST API. S3 keys only sign requests against
s3.nfyio.com. They are not accepted byapp.nfyio.com/api/.... - Bucket creation, deletion, or settings changes. These go through the backend API (
/api/object-storage/buckets) — a deliberate split so platform features like embedding pipelines and quota accounting stay consistent.
Rotation
The dashboard exposes a one-click Regenerate button on every access key — it issues a new secret and invalidates the old one in a single step. Update your client config with the new secret right after.
Choosing between the two
| Task | Use |
|---|---|
| Upload a file from a Lambda / cron / batch job | S3 access key |
| Download a file into your service | S3 access key |
| List or filter objects in a bucket | S3 access key |
| Trigger a chat / RAG query | Access token |
| Read notifications, billing, usage, quota | Access token |
| Manage members, projects, teams | Access token |
| Create or delete a bucket | Access token (backend API) |
| Provision new S3 access keys | Access token (backend API), or do it from the dashboard |
If your code does both (uploads + RAG queries), you’ll hold one of each.
Storage of secrets
- Treat both credential types as production secrets — keep them out of source control and out of client-side bundles.
- Prefer environment variables or a secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, etc).
- Set a short expiration on access tokens used inside CI.
- Restrict S3 access keys to a single bucket and the minimum permission they need.