CloudVantage / Bucket-as-a-Service
cloudvantage.com.ng ↗
CloudVantage · Bucket-as-a-Service

Store files, hand out links, over plain HTTP.

A REST API for object storage: create buckets, upload objects into them (flat or in folders), and share what's inside — as a permanent public link, a time-limited signed link, or an authenticated download. JSON in, JSON out; multipart for uploads.

Base URL https://buckets.cloudvantage.com.ng/bucketaas
Auth header
AuthToken
Request format
JSON · multipart/form-data
Response format
application/json
Rate limit
70 req / min

Powers every Try it panel below — expand one on any endpoint to send a real request from this page. Stored only in this browser (localStorage); never sent anywhere but your own requests. Only works when this page is served from the API's own origin — cross-origin previews will show a network error instead of a response.

Walkthrough

Quickstart

Four calls to go from credentials to a shareable link.

Get an auth token

Exchange your CloudVantage account email and password for a key. Every authenticated call below sends it back as an AuthToken header — prefixed with the literal word Bearer, a space, then the key.

curl -X POST https://buckets.cloudvantage.com.ng/bucketaas/tokens/generate-token \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "••••••••"}'

# response: { "key": "eyJhbGc...", "statuscode": "00", ... }
export AUTH_TOKEN="Bearer eyJhbGc..."

Create a bucket

curl -X POST https://buckets.cloudvantage.com.ng/bucketaas/proj_8f2ac1/buckets-aas/create-bucket \
  -H "AuthToken: $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "product-assets"}'

Upload a file

Uploads are private by default. Add ?expires_in_hours= (empty) to the URL instead to make it public.

curl -X POST "https://buckets.cloudvantage.com.ng/bucketaas/proj_8f2ac1/buckets-aas/product-assets/create-object?expires_in_hours=" \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "file=@logo.png"

Share it

The upload response includes a public_url (permanent, no auth needed). Anyone with the link can fetch it:

curl https://buckets.cloudvantage.com.ng/bucketaas/buckets-aas/public/a1B2c3D4.../download -o logo.png

Concepts

Authentication model

Every protected endpoint reads a custom AuthToken request header — not the standard Authorization header. There's no session or cookie state on this API; each request stands alone.

⚠

The value still needs a Bearer prefix. Only the header name is non-standard — its value is Bearer <key>, the same convention as Authorization: Bearer. Sending the bare key without Bearer in front of it fails with an error like {"statuscode": "01", "statusmessage": "API token is required"}, which reads like a missing-token error even though a token was sent.

#

Two token endpoints, one shape. /tokens/generate-token mints a new key pair; /tokens/get-token returns the account's existing one. Both accept the same email / password body and return the same shape. Pick whichever matches your flow — most integrations only ever need generate-token.

Authentication

Tokens

Both endpoints below are unauthenticated — they're how you obtain the AuthToken everything else requires.

POST /tokens/generate-token No auth

Authenticates with email and password and mints a new AuthToken.

Body — application/json
FieldTypeRequiredDescription
emailstringrequiredAccount email.
passwordstringrequiredAccount password.

Request

curl -X POST $BASE/tokens/generate-token \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com",
    "password": "••••••••"
  }'

Response 200

{
  "key": "eyJhbGciOiJIUzI1NiJ9.ab12cd34...",
  "statuscode": "00",
  "statusmessage": "Successful"
}

Error 400

{ "error": "Email and password are required" }

If the account service itself can't be reached, this returns 502 with {"error": "Failed to reach account service: ..."}.

Try it
POST /tokens/get-token No auth

Same request and response shape as Generate token, but retrieves the account's existing API key pair rather than issuing a new one.

Body — application/json
FieldTypeRequiredDescription
emailstringrequiredAccount email.
passwordstringrequiredAccount password.

Request

curl -X POST $BASE/tokens/get-token \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "••••••••"}'

Response 200

{
  "key": "eyJhbGciOiJIUzI1NiJ9.ab12cd34...",
  "statuscode": "00",
  "statusmessage": "Successful"
}

Error 400

{ "error": "Email and password are required" }
Try it

Projects

Projects

Every bucket and object lives under a project_id from your CloudVantage account.

GET /projects AuthToken required

Lists the projects available to the authenticated account.

Request

curl $BASE/projects \
  -H "AuthToken: $AUTH_TOKEN"

Response 200

{
  "projects": [
    { "id": "proj_8f2ac1", "name": "Marketing site" }
  ]
}

Error 401

{ "error": "AuthToken header missing" }
Try it

Buckets

Buckets

Buckets are namespaces for objects within a project. All bucket routes require AuthToken.

GET /{project_id}/buckets-aas/bucket-tiers AuthToken required

Lists the storage tiers available for buckets in this project — the valid values for tier on Create bucket.

Request

curl $BASE/proj_8f2ac1/buckets-aas/bucket-tiers \
  -H "AuthToken: $AUTH_TOKEN"

Error 401

{ "error": "AuthToken header missing" }

Response 200

{
  "tiers": [
    {
      "name": "Basic",
      "storage_limit_gb": 500,
      "monthly_price": 10.0,
      "yearly_price": 30.0,
      "zone_name": "Lagos"
    }
  ],
  "statuscode": "00",
  "statusmessage": "successful"
}
Try it
GET /{project_id}/buckets-aas/list-buckets AuthToken required

Lists every bucket in the given project.

Request

curl $BASE/proj_8f2ac1/buckets-aas/list-buckets \
  -H "AuthToken: $AUTH_TOKEN"

Response 200

{
  "buckets": [
    {
      "name": "product-assets",
      "tier": "Basic",
      "public": false,
      "created": "Monday, June 1st, 2026 9:12 AM",
      "size_mb": 12.4832
    }
  ],
  "statuscode": "00",
  "statusmessage": "successful"
}

Error 401

{ "error": "AuthToken header missing" }
Try it
POST /{project_id}/buckets-aas/create-bucket AuthToken required

Creates a new bucket in the given project.

Body — application/json
FieldTypeRequiredDescription
namestringrequiredName for the new bucket, unique within the project's zone.
publicbooleanoptionalDefault false. Makes the bucket itself publicly readable when true — every object placed in it stays public even if uploaded with expires_in_hours set.
tierstringoptionalStorage tier for the bucket, e.g. Basic — see List bucket tiers for the available options.

Request

curl -X POST $BASE/proj_8f2ac1/buckets-aas/create-bucket \
  -H "AuthToken: $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "product-assets",
    "public": false,
    "tier": "Basic"
  }'

Response 201

{
  "message": "bucket storage created successfully",
  "statuscode": "00",
  "statusmessage": "bucket storage created successfully"
}

Error 401

{ "error": "AuthToken header missing" }
Try it
GETDELETE /{project_id}/buckets-aas/{bucket_name} AuthToken required

GET returns bucket metadata. DELETE removes the bucket.

Request — GET

curl $BASE/proj_8f2ac1/buckets-aas/product-assets \
  -H "AuthToken: $AUTH_TOKEN"

Request — DELETE

curl -X DELETE $BASE/proj_8f2ac1/buckets-aas/product-assets \
  -H "AuthToken: $AUTH_TOKEN"

401 if AuthToken is missing. Otherwise the storage status and body are passed through — e.g. 404 if the bucket doesn't exist.

Try it
GET /{project_id}/buckets-aas/{bucket_name}/objects AuthToken required

Lists every object in a bucket, including folder contents — objects inside a folder are nested under that folder's children array rather than listed flat.

Request

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/objects \
  -H "AuthToken: $AUTH_TOKEN"

Response 200

{
  "objects": [
    {
      "file_name": "logo.png",
      "file_size": 0.047,
      "is_folder": false,
      "created": "Monday, June 1st, 2026 9:12 AM",
      "last_modified": "Monday, June 1st, 2026 9:12 AM",
      "bucket": { "name": "product-assets", "tier": "Basic", "public": false }
    },
    {
      "folder_name": "invoices/",
      "is_folder": true,
      "folder_size": 1.284,
      "children": [
        { "file_name": "march.pdf", "file_size": 1.284, "folder_name": "invoices/" }
      ]
    }
  ],
  "statuscode": "00",
  "statusmessage": "successful"
}

Error 401

{ "error": "AuthToken header missing" }
Try it

Objects

Objects

Uploads are multipart/form-data. Video files are capped at 100 MB and images/PDFs at 20 MB by default — see Limits.

POST /{project_id}/buckets-aas/{bucket_name}/create-object AuthToken required

Uploads a single file to the root of a bucket. We queue the actual upload and return immediately — poll status_url (see Check upload status) to confirm it finished.

Query string
FieldTypeRequiredDescription
expires_in_hoursintegeroptionalPass this param empty (?expires_in_hours=) to publish the object permanently. Omit the param entirely, or give it a number, to keep the object private — the number itself isn't enforced as a real expiry.
Body — multipart/form-data
FieldTypeRequiredDescription
filefilerequiredThe file to upload.
◐

Private by default. Without ?expires_in_hours=, the file is read back through the authenticated object, download, or stream endpoints using your AuthToken — the same route the response's object_url already points at. There's no request-body flag for going public; it's query-string only.

⚠

A public bucket makes every object in it public. If the bucket itself was created with public: true, objects uploaded into it are always public, regardless of expires_in_hours.

Request — private object (default)

curl -X POST $BASE/proj_8f2ac1/buckets-aas/product-assets/create-object \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "file=@logo.png"

Request — public object

curl -X POST "$BASE/proj_8f2ac1/buckets-aas/product-assets/create-object?expires_in_hours=" \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "file=@logo.png"

Response 202 — public (?expires_in_hours= given)

{
  "statusmessage": "File upload in progress",
  "statuscode": "00",
  "filename": "logo.png",
  "object_url": "$BASE/proj_8f2ac1/buckets-aas/product-assets/objects/logo.png/stream",
  "task_id": "97694985-e354-41a8-9861-1af4271b015c",
  "status_url": "$BASE/buckets-aas/upload-status/97694985-e354-41a8-9861-1af4271b015c",
  "share_token": "a1B2c3D4...",
  "public_url": "$BASE/buckets-aas/public/a1B2c3D4.../download"
}

Error 400

{ "statusmessage": "No file provided", "statuscode": "01" }

A private upload (the default — no expires_in_hours param) returns the same shape minus share_token/public_url. Oversized files return 400 too, e.g. {"statusmessage": "Image/PDF file size exceeds the limit of 20 MB", "statuscode": "01"} — see Limits.

Try it
POST /{project_id}/buckets-aas/{bucket_name}/create-objects AuthToken required

Uploads several files to the root of a bucket in one call — same public/private contract as single upload, applied to every file in the batch. We queue each file individually and return immediately, with its own task_id/status_url per file (see Check upload status).

Query string
FieldTypeRequiredDescription
expires_in_hoursintegeroptionalPass this param empty (?expires_in_hours=) to publish every file in the batch permanently. Omit the param entirely, or give it a number, to keep them all private — the number itself isn't enforced as a real expiry.
Body — multipart/form-data
FieldTypeRequiredDescription
filesfile[]requiredRepeat the files field for each file in the batch.
◐

Private by default — same as single upload: every file stays private unless you pass ?expires_in_hours=<empty>, which gives each one its own share_token/public_url. A bucket created with public: true makes them all public regardless.

Request — public (?expires_in_hours= given)

curl -X POST "$BASE/proj_8f2ac1/buckets-aas/product-assets/create-objects?expires_in_hours=" \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "files=@logo.png" \
  -F "files=@favicon.ico"

Response 202

{
  "statusmessage": "File upload in progress",
  "statuscode": "00",
  "objects": [
    {
      "filename": "logo.png",
      "object_url": "$BASE/proj_8f2ac1/buckets-aas/product-assets/objects/logo.png/stream",
      "task_id": "bcbf6fd7-2d25-4c69-bc88-0a4bb0a96669",
      "status_url": "$BASE/buckets-aas/upload-status/bcbf6fd7-2d25-4c69-bc88-0a4bb0a96669",
      "share_token": "8x1GmxTg...",
      "public_url": "$BASE/buckets-aas/public/8x1GmxTg.../download"
    },
    {
      "filename": "favicon.ico",
      "object_url": "$BASE/proj_8f2ac1/buckets-aas/product-assets/objects/favicon.ico/stream",
      "task_id": "dff56a37-ed2e-423f-bdbb-bb9d9834d440",
      "status_url": "$BASE/buckets-aas/upload-status/dff56a37-ed2e-423f-bdbb-bb9d9834d440",
      "share_token": "R6wQSGD4...",
      "public_url": "$BASE/buckets-aas/public/R6wQSGD4.../download"
    }
  ]
}

Error 400

{
  "statusmessage": "File 'favicon.ico': Image/PDF file size exceeds the limit of 20 MB",
  "statuscode": "01"
}

A private batch (the default — no expires_in_hours param) returns the same per-object shape minus share_token/public_url.

Try it
GET /buckets-aas/upload-status/{task_id} AuthToken required

Checks the background upload task returned by Upload object's task_id/status_url.

Response fields
FieldDescription
statusPENDING, STARTED, RETRY, SUCCESS, or FAILURE. PENDING covers both "still running" and "unknown task_id" — there's no way to tell those apart until a result exists.
resultPresent once status is SUCCESS or FAILURE. Its nested success field is the real signal — the task itself finishes without raising even when the upload fails, so check result.success, not just status.

Request

curl $BASE/buckets-aas/upload-status/97694985-e354-41a8-9861-1af4271b015c \
  -H "AuthToken: $AUTH_TOKEN"

Response 200 — still in progress

{
  "task_id": "97694985-e354-41a8-9861-1af4271b015c",
  "status": "PENDING",
  "statuscode": "00",
  "statusmessage": "successful"
}

Response 200 — finished

{
  "task_id": "97694985-e354-41a8-9861-1af4271b015c",
  "status": "SUCCESS",
  "result": { "success": true, "message": "object uploaded successfully" },
  "statuscode": "00",
  "statusmessage": "successful"
}

A failed upload still reports status: "SUCCESS" (the task ran to completion) with result: {"success": false, "message": "..."} describing what went wrong — e.g. "project not found" or "local bucket not found".

Try it
GETDELETE /{project_id}/buckets-aas/{bucket_name}/objects/{obj_name} AuthToken required

GET returns object metadata. DELETE removes the object.

Request — GET

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/objects/logo.png \
  -H "AuthToken: $AUTH_TOKEN"

Request — DELETE

curl -X DELETE $BASE/proj_8f2ac1/buckets-aas/product-assets/objects/logo.png \
  -H "AuthToken: $AUTH_TOKEN"

401 if AuthToken is missing. Otherwise the storage status and body are passed through — e.g. 404 if the object doesn't exist.

Try it
GET /{project_id}/buckets-aas/{bucket_name}/objects/{obj_name}/download AuthToken required

Streams the raw file back with a Content-Disposition: attachment header, for saving to disk.

Request

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/objects/logo.png/download \
  -H "AuthToken: $AUTH_TOKEN" \
  -o logo.png

Response 200

binary file content
Content-Disposition: attachment; filename=logo.png

This route always responds 200. If the object can't be retrieved, the error payload is returned as the downloaded content instead of a normal JSON error — check the content-type/size to confirm you received the real file.

Try it
GET /{project_id}/buckets-aas/{bucket_name}/objects/{obj_name}/stream AuthToken required

Same as download, for playing or previewing inline (e.g. video/audio players) rather than saving.

Request

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/objects/demo.mp4/stream \
  -H "AuthToken: $AUTH_TOKEN" \
  -o demo.mp4

Response 200

binary file content
Content-Type: video/mp4

Error 404

{ "error": "Failed to stream object" }
Try it

Folders

Folders

Folders group objects under a path prefix within a bucket. Folder uploads share the same public/private mechanism as the root create-object/create-objects endpoints — a share_token/public_url pair, controlled by expires_in_hours.

POSTDELETE /{project_id}/buckets-aas/{bucket_name}/create-delete-folder/{folder_name} AuthToken required

POST creates the folder. DELETE removes it.

Request — create

curl -X POST $BASE/proj_8f2ac1/buckets-aas/product-assets/create-delete-folder/invoices \
  -H "AuthToken: $AUTH_TOKEN"

Request — delete

curl -X DELETE $BASE/proj_8f2ac1/buckets-aas/product-assets/create-delete-folder/invoices \
  -H "AuthToken: $AUTH_TOKEN"

401 if AuthToken is missing. Otherwise the storage status and body are passed through.

Try it
GET /{project_id}/buckets-aas/{bucket_name}/{folder_name}/objects AuthToken required

Lists every object inside a folder, flat — unlike List objects, there's no nesting since the folder is already the scope.

Request

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/invoices/objects \
  -H "AuthToken: $AUTH_TOKEN"

Response 200

{
  "objects": [
    { "file_name": "march.pdf", "file_size": 1.284, "folder_name": "invoices/",
      "created": "Monday, June 1st, 2026 9:12 AM", "last_modified": "Monday, June 1st, 2026 9:12 AM" }
  ],
  "statuscode": "00",
  "statusmessage": "successful"
}

Error 401

{ "error": "AuthToken header missing" }

401 if AuthToken is missing. Otherwise the storage status and body are passed through — e.g. 404 if the folder doesn't exist.

Try it
POST /{project_id}/buckets-aas/{bucket_name}/upload-object-folder/{folder_name} AuthToken required

Uploads a file into a folder. Same public/private contract as Upload object.

Query string
FieldTypeRequiredDescription
expires_in_hoursintegeroptionalPass this param empty (?expires_in_hours=) to publish the object permanently. Omit the param entirely, or give it a number, to keep it private — the number itself isn't enforced as a real expiry.
Body — multipart/form-data
FieldTypeRequiredDescription
filefilerequiredThe file to upload.
◐

Private by default — same as Upload object: the response only includes a share_token/public_url when you pass ?expires_in_hours=<empty>. A bucket created with public: true makes it public regardless.

Request — private object (default)

curl -X POST "$BASE/proj_8f2ac1/buckets-aas/product-assets/upload-object-folder/invoices" \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "file=@march.pdf"

Request — public object

curl -X POST "$BASE/proj_8f2ac1/buckets-aas/product-assets/upload-object-folder/invoices?expires_in_hours=" \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "file=@march.pdf"

Response 201 — public (?expires_in_hours= given)

{
  "message": "File uploaded successfully",
  "statuscode": "00",
  "statusmessage": "File uploaded successfully",
  "object_url": "$BASE/proj_8f2ac1/buckets-aas/product-assets/invoices/march.pdf/stream",
  "share_token": "1iX9t7SI...",
  "public_url": "$BASE/buckets-aas/public/1iX9t7SI.../download"
}

Error 400

{ "statusmessage": "Video file size exceeds the limit of 100 MB", "statuscode": "01" }

A private upload (the default — no expires_in_hours param) returns the same shape minus share_token/public_url.

Try it
POST /{project_id}/buckets-aas/{bucket_name}/upload-objects-folder/{folder_name} AuthToken required

Uploads several files into a folder in one call — same public/private contract as single folder upload, applied to every file in the batch. Unlike the root Upload multiple objects, this runs synchronously: the response only returns once every file has finished uploading, with one entry per file (no task_id/polling needed).

Query string
FieldTypeRequiredDescription
expires_in_hoursintegeroptionalPass this param empty (?expires_in_hours=) to publish every file in the batch permanently. Omit the param entirely, or give it a number, to keep them all private.
Body — multipart/form-data
FieldTypeRequiredDescription
filesfile[]requiredRepeat the files field for each file in the batch.
◐

Private by default — same as single folder upload: every file stays private unless you pass ?expires_in_hours=<empty>, which gives each one its own share_token/public_url. A bucket created with public: true makes them all public regardless.

Request — public (?expires_in_hours= given)

curl -X POST "$BASE/proj_8f2ac1/buckets-aas/product-assets/upload-objects-folder/invoices?expires_in_hours=" \
  -H "AuthToken: $AUTH_TOKEN" \
  -F "files=@march.pdf" \
  -F "files=@april.pdf"

Response 201

{
  "statusmessage": "Upload complete",
  "statuscode": "00",
  "objects": [
    {
      "filename": "march.pdf",
      "object_url": "$BASE/proj_8f2ac1/buckets-aas/product-assets/invoices/march.pdf/stream",
      "share_token": "1iX9t7SI...",
      "public_url": "$BASE/buckets-aas/public/1iX9t7SI.../download"
    },
    {
      "filename": "april.pdf",
      "object_url": "$BASE/proj_8f2ac1/buckets-aas/product-assets/invoices/april.pdf/stream",
      "share_token": "R6wQSGD4...",
      "public_url": "$BASE/buckets-aas/public/R6wQSGD4.../download"
    }
  ]
}

Error 400

{
  "statusmessage": "File 'april.pdf': Image/PDF file size exceeds the limit of 20 MB",
  "statuscode": "01"
}

If a single file in the batch fails to upload, its entry has an error field instead of object_url/share_token/public_url — the rest of the batch still completes. A private batch (the default — no expires_in_hours param) returns the same per-object shape minus share_token/public_url.

Try it
GET /{project_id}/buckets-aas/{bucket_name}/download-object/{folder_name}/{obj_name} AuthToken required

Downloads a file that lives inside a folder.

Request

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/download-object/invoices/march.pdf \
  -H "AuthToken: $AUTH_TOKEN" \
  -o march.pdf

401 if AuthToken is missing. Like Download object, this route always responds 200 — a failed lookup comes back as the error payload in place of file content.

Try it
GET /{project_id}/buckets-aas/{bucket_name}/stream-object/{folder_name}/{obj_name} AuthToken required

Streams a file that lives inside a folder, for inline playback.

Request

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/stream-object/reels/promo.mp4 \
  -H "AuthToken: $AUTH_TOKEN" \
  -o promo.mp4

401 if AuthToken is missing; 404 with {"error": "Failed to stream object"} if the object can't be found.

Try it
GETDELETE /{project_id}/buckets-aas/{bucket_name}/delete-get-object/{folder_name}/{obj_name} AuthToken required

Reads (GET) or removes (DELETE) a single object inside a folder.

Request — GET

curl $BASE/proj_8f2ac1/buckets-aas/product-assets/delete-get-object/invoices/march.pdf \
  -H "AuthToken: $AUTH_TOKEN"

Request — DELETE

curl -X DELETE $BASE/proj_8f2ac1/buckets-aas/product-assets/delete-get-object/invoices/march.pdf \
  -H "AuthToken: $AUTH_TOKEN"

401 if AuthToken is missing. Otherwise the storage's status and body are passed through.

Try it

Public sharing

Public sharing

Objects uploaded via Upload object or Upload multiple objects with an empty expires_in_hours query param get a share_token and a ready-to-use public_url in the response. These two routes serve that token — no AuthToken, ever.

GET /buckets-aas/public/{share_token}/download No auth

Downloads a public object as an attachment.

Request

curl $BASE/buckets-aas/public/a1B2c3D4.../download -o logo.png

Error 404

{ "error": "Failed to download object" }
Try it
GET /buckets-aas/public/{share_token}/stream No auth

Streams a public object inline — drop this straight into an <img>, <video>, or <audio> tag.

Request

curl $BASE/buckets-aas/public/a1B2c3D4.../stream -o preview.mp4

Error 404

{ "error": "Failed to stream object" }
Try it

Reference

Errors & status codes

Errors are JSON. Most carry an error field; some — especially the token endpoints — use the upstream statuscode / statusmessage pair instead ("00" means success).

StatusMeaningTypical body
400Missing or invalid input — e.g. no file on an upload, or a missing email/password.{"error": "..."}
401Missing AuthToken header.{"error": "..."}
404Resource not found, or unmatched route entirely.{"statuscode": "01", "statusmessage": "Not Found"}
429Rate limit exceeded — see Limits.{"detail": "Request was throttled."}
502The upstream account service couldn't be reached.{"error": "Failed to reach account service: ..."}
500Unhandled server error.{"statuscode": "01", "statusmessage": "Server Error"}

Limits

LimitDefault
Requests70 per minute, per account (and per anonymous IP on unauthenticated routes)
Video uploads100 MB — .mp4, .mov, .avi, or any video/* content type
Image / PDF uploads20 MB — .jpg, .jpeg, .png, .gif, .webp, .svg, .pdf, or any image/* content type

Oversized uploads return 400 with a statusmessage naming the limit that was hit. Exact limits are configured per deployment and may differ from the defaults above.