Skip to content

API Endpoints

Base URL: https://api.atiru.io

Authentication: Authorization: Bearer <api_key> or X-Api-Key: <api_key>

Auth

MethodPathAuthDescription
POST/auth/registerNoRegister
POST/auth/loginNoLogin
POST/auth/forgot-passwordNoRequest password reset
POST/auth/api-keysJWT onlyCreate API key
GET/auth/api-keysJWT onlyList API keys
DELETE/auth/api-keys/:idJWT onlyRevoke API key

POST /auth/register

Code example

bash
curl -X POST "https://api.atiru.io/auth/register" \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your_password","redirect_to":"https://app.example.com/auth/confirm-success"}'
javascript
const res = await fetch('https://api.atiru.io/auth/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'you@example.com',
    password: 'your_password',
    redirect_to: 'https://app.example.com/auth/confirm-success',
  }),
})
const data = await res.json()
python
import requests

res = requests.post(
    'https://api.atiru.io/auth/register',
    json={
        'email': 'you@example.com',
        'password': 'your_password',
        'redirect_to': 'https://app.example.com/auth/confirm-success',
    },
)
data = res.json()

Request

  • Body
json
{
  "email": "you@example.com",
  "password": "your_password",
  "redirect_to": "https://app.example.com/auth/confirm-success"
}
FieldTypeRequiredDescription
emailstringYesEmail address
passwordstringYesMin 6 characters
redirect_tostringNoURL after email confirmation

Response

  • 201 — Success
json
{
  "message": "Check your email to confirm your account.",
  "user": {
    "id": "uuid",
    "email": "you@example.com"
  }
}
  • 400 — Bad request (e.g. invalid email, short password)

POST /auth/login

Code example

bash
curl -X POST "https://api.atiru.io/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your_password"}'
javascript
const res = await fetch('https://api.atiru.io/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'you@example.com', password: 'your_password' }),
})
const { user, session } = await res.json()
const accessToken = session.access_token
python
import requests

res = requests.post(
    'https://api.atiru.io/auth/login',
    json={'email': 'you@example.com', 'password': 'your_password'},
)
data = res.json()
access_token = data['session']['access_token']

Request

  • Body
json
{
  "email": "you@example.com",
  "password": "your_password"
}

Response

  • 200 — Success
json
{
  "user": {
    "id": "uuid",
    "email": "you@example.com",
    "created_at": "2024-01-15T12:00:00.000Z",
    "updated_at": "2024-01-15T12:00:00.000Z"
  },
  "session": {
    "access_token": "eyJ...",
    "refresh_token": "...",
    "expires_in": 3600,
    "expires_at": 1705334400,
    "token_type": "bearer"
  }
}
  • 401 — Invalid credentials
  • 403 — Email not verified. Body includes code: "EMAIL_NOT_VERIFIED".

POST /auth/api-keys

Requires JWT (login token). API key auth returns 403.

Code example

bash
curl -X POST "https://api.atiru.io/auth/api-keys" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Production server"}'
javascript
const res = await fetch('https://api.atiru.io/auth/api-keys', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_JWT_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'Production server' }),
})
const { id, key, key_prefix, name, created_at } = await res.json()
python
import requests

res = requests.post(
    'https://api.atiru.io/auth/api-keys',
    headers={'Authorization': 'Bearer YOUR_JWT_TOKEN'},
    json={'name': 'Production server'},
)
data = res.json()

Request

  • Body
json
{
  "name": "Production server"
}
FieldTypeRequiredDescription
namestringNoLabel for the API key

Response

  • 201 — Success. The key value is returned only once; store it securely.
json
{
  "id": "uuid",
  "key": "atiru_xxxxxxxxxxxx",
  "key_prefix": "atiru_xxxx",
  "name": "Production server",
  "created_at": "2024-01-15T12:00:00.000Z"
}
  • 401 — Unauthorized
  • 403 — API key cannot manage API keys (use JWT)

GET /auth/api-keys

Code example

bash
curl -X GET "https://api.atiru.io/auth/api-keys" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
javascript
const res = await fetch('https://api.atiru.io/auth/api-keys', {
  headers: { 'Authorization': 'Bearer YOUR_JWT_TOKEN' },
})
const { api_keys } = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/auth/api-keys',
    headers={'Authorization': 'Bearer YOUR_JWT_TOKEN'},
)
data = res.json()
api_keys = data['api_keys']

Request

  • No query params or body.

Response

  • 200 — Success
json
{
  "api_keys": [
    {
      "id": "uuid",
      "key_prefix": "atiru_xxxx",
      "name": "Production server",
      "created_at": "2024-01-15T12:00:00.000Z",
      "last_used_at": "2024-01-16T10:30:00.000Z"
    }
  ]
}
  • 401 — Unauthorized
  • 403 — API key cannot list API keys (use JWT)

DELETE /auth/api-keys/:id

Code example

bash
curl -X DELETE "https://api.atiru.io/auth/api-keys/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
javascript
await fetch('https://api.atiru.io/auth/api-keys/550e8400-e29b-41d4-a716-446655440000', {
  method: 'DELETE',
  headers: { 'Authorization': 'Bearer YOUR_JWT_TOKEN' },
})
python
import requests

requests.delete(
    'https://api.atiru.io/auth/api-keys/550e8400-e29b-41d4-a716-446655440000',
    headers={'Authorization': 'Bearer YOUR_JWT_TOKEN'},
)

Request

  • Path: :id — API key UUID.

Response

  • 204 — No body. Key revoked.
  • 401 — Unauthorized
  • 403 — API key cannot revoke (use JWT)
  • 404 — Key not found

Files

MethodPathAuthDescription
POST/filesYesUpload file
GET/filesYesList files
GET/files/:idYesGet one file by file_id
DELETE/files/:idYesDelete file
POST/files/bulk-deleteYesBulk delete (max 100 IDs)

POST /files

Code example

bash
curl -X POST "https://api.atiru.io/files" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: image/png" \
  -H "x-file-name: example.png" \
  --data-binary @/path/to/example.png
javascript
const fileBuffer = await readFile('./example.png')
const res = await fetch('https://api.atiru.io/files', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'image/png',
    'x-file-name': 'example.png',
  },
  body: fileBuffer,
})
const { file, message } = await res.json()
python
import requests

with open('example.png', 'rb') as f:
    res = requests.post(
        'https://api.atiru.io/files',
        headers={
            'Authorization': 'Bearer YOUR_API_KEY',
            'Content-Type': 'image/png',
            'x-file-name': 'example.png',
        },
        data=f.read(),
    )
data = res.json()
print(data['file']['public_url'])

Request

  • Query
ParamTypeDefaultDescription
isPublicbooleantrueSet to false for private uploads
  • Headers: Content-Type (required, MIME type), x-file-name (optional)
  • Body: Raw binary (file bytes)

Response

  • 201 — Success
json
{
  "file": {
    "id": "uuid",
    "user_id": "uuid",
    "file_id": "abc123",
    "name": "example.png",
    "content_type": "image/png",
    "size": 12345,
    "public_url": "https://cdn.atiru.io/m/abc123",
    "default_url": "https://cdn.atiru.io/m/abc123",
    "default_download_url": "https://cdn.atiru.io/d/abc123",
    "public_download_url": "https://cdn.atiru.io/d/abc123",
    "created_at": "2024-01-15T12:00:00.000Z",
    "is_public": true
  },
  "message": "File uploaded"
}
  • 400 — Content-Type not allowed
  • 401 — Unauthorized
  • 403 — Trial ended, storage limit, or file count limit
  • 413 — File too large (code: "FILE_TOO_LARGE")

GET /files

Code example

bash
curl -X GET "https://api.atiru.io/files" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
const res = await fetch('https://api.atiru.io/files', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
const { files } = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/files',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
files = res.json()['files']

Request

  • No query params or body.

Response

  • 200 — Success
json
{
  "files": [
    {
      "id": "uuid",
      "user_id": "uuid",
      "file_id": "abc123",
      "name": "example.png",
      "content_type": "image/png",
      "size": 12345,
      "public_url": "https://cdn.atiru.io/m/abc123",
      "default_url": "https://cdn.atiru.io/m/abc123",
      "default_download_url": "https://cdn.atiru.io/d/abc123",
      "public_download_url": "https://cdn.atiru.io/d/abc123",
      "created_at": "2024-01-15T12:00:00.000Z",
      "is_public": true
    }
  ]
}
  • 401 — Unauthorized

GET /files/:id

Replace :id with the file's file_id.

Code example

bash
curl -X GET "https://api.atiru.io/files/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
const res = await fetch('https://api.atiru.io/files/abc123', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
const file = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/files/abc123',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
file = res.json()

Request

  • Path: :id — File ID (file_id).

Response

  • 200 — Success. Single file object (same shape as items in GET /files).
  • 401 — Unauthorized
  • 404 — File not found

DELETE /files/:id

Code example

bash
curl -X DELETE "https://api.atiru.io/files/abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
await fetch('https://api.atiru.io/files/abc123', {
  method: 'DELETE',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
python
import requests

requests.delete(
    'https://api.atiru.io/files/abc123',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

Request

  • Path: :id — File ID (file_id).

Response

  • 204 — No body. File deleted.
  • 401 — Unauthorized
  • 403 — Trial ended
  • 404 — File not found

POST /files/bulk-delete

Code example

bash
curl -X POST "https://api.atiru.io/files/bulk-delete" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":["abc123","def456"]}'
javascript
const res = await fetch('https://api.atiru.io/files/bulk-delete', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ ids: ['abc123', 'def456'] }),
})
const { deleted, errors } = await res.json()
python
import requests

res = requests.post(
    'https://api.atiru.io/files/bulk-delete',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
    },
    json={'ids': ['abc123', 'def456']},
)
data = res.json()

Request

  • Body
json
{
  "ids": ["abc123", "def456"]
}
FieldTypeRequiredDescription
idsstring[]Yes1–100 file IDs

Response

  • 200 — Success
json
{
  "deleted": 2,
  "errors": [
    {
      "id": "nonexistent",
      "error": "File not found"
    }
  ]
}
  • 400 — Bad request (e.g. empty ids)
  • 401 — Unauthorized

Settings

MethodPathAuthDescription
GET/settingsYesGet user settings
PATCH/settingsYesUpdate settings

GET /settings

Code example

bash
curl -X GET "https://api.atiru.io/settings" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
const res = await fetch('https://api.atiru.io/settings', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
const settings = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/settings',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
settings = res.json()

Request

  • No query params or body.

Response

  • 200 — Success
json
{
  "public_url_base": "https://cdn.example.com",
  "max_upload_size_bytes": 52428800
}
  • 401 — Unauthorized

PATCH /settings

Code example

bash
curl -X PATCH "https://api.atiru.io/settings" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"public_url_base":"https://cdn.example.com","max_upload_size_bytes":20971520}'
javascript
const res = await fetch('https://api.atiru.io/settings', {
  method: 'PATCH',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    public_url_base: 'https://cdn.example.com',
    max_upload_size_bytes: 20971520,
  }),
})
const settings = await res.json()
python
import requests

res = requests.patch(
    'https://api.atiru.io/settings',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'public_url_base': 'https://cdn.example.com',
        'max_upload_size_bytes': 20971520,
    },
)
settings = res.json()

Request

  • Body
json
{
  "public_url_base": "https://cdn.example.com",
  "max_upload_size_bytes": 20971520
}

Both fields optional; send only the ones you want to update.

Response

  • 200 — Success. Same shape as GET /settings.
  • 400 — Bad request
  • 401 — Unauthorized

Usage

MethodPathAuthDescription
GET/usageYesGet usage stats

GET /usage

Code example

bash
curl -X GET "https://api.atiru.io/usage" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
const res = await fetch('https://api.atiru.io/usage', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
const usage = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/usage',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
usage = res.json()

Request

  • No query params or body.

Response

  • 200 — Success
json
{
  "storage_bytes": 1048576,
  "files_count": 42,
  "origin_reads": 150,
  "image_ops": 80,
  "period_start": "2024-01-01T00:00:00.000Z",
  "period_end": "2024-01-31T23:59:59.000Z"
}
  • 401 — Unauthorized

Logs

MethodPathAuthDescription
GET/logsYesGet activity logs

GET /logs

Code example

bash
curl -X GET "https://api.atiru.io/logs?page=1&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
const res = await fetch('https://api.atiru.io/logs?page=1&limit=20', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
const { logs, total, page, limit } = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/logs',
    params={'page': 1, 'limit': 20},
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
data = res.json()

Request

  • Query
ParamTypeDefaultDescription
pagenumber1Page number
limitnumberItems per page

Response

  • 200 — Success
json
{
  "logs": [
    {
      "id": "uuid",
      "method": "GET",
      "path": "/files",
      "status_code": 200,
      "request_size_bytes": null,
      "created_at": "2024-01-15T12:00:00.000Z",
      "metadata": {}
    }
  ],
  "total": 100,
  "page": 1,
  "limit": 20
}
  • 401 — Unauthorized

Profile

MethodPathAuthDescription
GET/profileYesGet profile (user + plan)

GET /profile

Code example

bash
curl -X GET "https://api.atiru.io/profile" \
  -H "Authorization: Bearer YOUR_API_KEY"
javascript
const res = await fetch('https://api.atiru.io/profile', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
})
const profile = await res.json()
python
import requests

res = requests.get(
    'https://api.atiru.io/profile',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
profile = res.json()

Request

  • No query params or body.

Response

  • 200 — Success. User and plan info, including subscription_canceled_at, access_until for billing display.
  • 401 — Unauthorized

Reference (no auth)

MethodPathAuthDescription
GET/reference/allowed-content-typesNoList allowed MIME types for upload
GET/reference/for-agentsNoAgent discovery payload
GET/reference/openapi.jsonNoOpenAPI 3.0 spec

File schema

File objects returned by the API follow this shape:

json
{
  "id": "uuid",
  "user_id": "uuid",
  "file_id": "string",
  "name": "string or null",
  "content_type": "string or null",
  "size": "number or null",
  "public_url": "string or null",
  "default_url": "string or null",
  "default_download_url": "string or null",
  "public_download_url": "string or null",
  "created_at": "string or null",
  "is_public": "boolean or null"
}