# REST API reference

- Base URL: `https://strovio.xyz/api/v1`
- Machine-readable: [OpenAPI 3.1 document](https://strovio.xyz/openapi.json)
- Auth: `Authorization: Bearer sk_live_...`, or `X-API-Key: sk_live_...` if you cannot set an `Authorization` header. Create keys at [strovio.xyz/developer](https://strovio.xyz/developer).
- Errors: JSON `{ "error": "...", "code": "...", "doc_url": "..." }`. See [Errors](https://strovio.xyz/docs/errors).
- Keys: `{path}` is exactly the path you uploaded to, such as `reports/q1.pdf`, or the full key from a response, such as `uploads/<account>/private/reports/q1.pdf`. Encode each segment, for example a space as `%20`. If the path exists as both a public and a private file, the path alone returns `409 ambiguous_key`.

## File object

| Field | Type | Notes |
|---|---|---|
| `key` | string | Full key: `uploads/<account>/<access>/<path>` |
| `name` | string | Your path on upload responses; the file name on list and get |
| `size` | integer | Bytes |
| `contentType` | string | Media type |
| `access` | `public` or `private` | |
| `url` | string or null | Public URL, signed URL (get, private files) or null |
| `expiresIn` | integer or null | Get only: 3600 for private files, null for public |
| `createdAt`, `updatedAt` | string | ISO 8601 |

## PUT /files/{path}

Upload or replace a file. Body: the raw bytes, up to 512 MB (536,870,912 bytes). Uploading to a path that exists with the same access replaces it; with the other access it creates a second file.

Headers: `Content-Type` (stored with the file), `X-Access: public` for a public file (default private).

`201` returns the file object.

## GET /files

List files, newest first. Query: `prefix` (key contains this text anywhere: `reports/` also matches `old/reports/x.pdf`), `limit` (whole number from 1, default 1000, values above 1000 are treated as 1000).

`200` returns `{ "objects": [file], "count": n }`.

## GET /files/{path}

Get a file's details and a download `url`. `200` returns the file object with `expiresIn`. `404 file_not_found` if no file matches, `409 ambiguous_key` if the path is both public and private.

## HEAD /files/{path}

`200` with `Content-Length`, `Content-Type`, `X-Access` and `Last-Modified` headers, `404` or `409`. No body.

## DELETE /files/{path}

Permanently delete a file and its share links. `200` returns `{ "ok": true, "key": "..." }`.

## POST /files/multipart/start

Body: `{ "key", "size", "contentType"?, "access"? }`. `200` returns `{ "uploadId", "s3Key", "bucket", "parts": [{ "partNumber", "url", "contentLength" }] }`. See [Upload large files](https://strovio.xyz/docs/large-uploads).

## POST /files/multipart/complete

Body: `{ "s3Key", "uploadId", "key", "parts": [{ "PartNumber", "ETag" }], "contentType"?, "access"? }`. `201` returns the file object.

## POST /files/presign-put

Body: `{ "key", "size", "contentType"?, "access"? }`. `200` returns `{ "putUrl", "s3Key", "bucket" }`. `PUT` the bytes to `putUrl` within one hour with the same `Content-Type`.

## POST /files/complete

Body: `{ "key", "contentType"?, "access"? }`, after a successful `PUT` to a `putUrl`. `201` returns the file object.

## GET /api/health

`https://strovio.xyz/api/health` needs no key and returns `{"ok":true,...}` when the service is up.

## Idempotency and retries

Writes are keyed by path and access: retrying a `PUT` or a complete call with the same key and access replaces the same file and never creates a duplicate. The API does not store `Idempotency-Key` values. Retry `5xx` errors with backoff; do not retry `4xx` errors without changing the request. A retried `DELETE` whose first attempt succeeded returns `404 file_not_found`.

## Not available with an API key

Share links, folders, stars, trash, search and billing are dashboard features and need a signed-in browser session.

---

Source: https://strovio.xyz/docs/api
All docs for agents: https://strovio.xyz/llms.txt
