Skip to main content

First checks

Before deep debugging, confirm:
  1. The base URL ends with /api.
  2. Both X-Public-Key and X-Secret-Key are present.
  3. The key is active and not expired.
  4. The key belongs to a company account.
  5. The key includes both the bucket scope and the resource scope for the operation.
  6. The target bucket is within the key’s restriction.
  7. The company has active billing, or a valid trial.
  8. The owning user has active encryption keys for uploads.

Symptom: every request returns 401

A 401 does not tell you which of these is true. Do not retry aggressively; fix the credential.

Symptom: 403 API_COMPANY_ONLY

The key belongs to an individual account. The developer REST API is company-only.
  • Switch to a company workspace.
  • Create a company key.
  • If you are building a backup agent, use the device-bound key flow instead.

Symptom: 403 without a code

Usually a missing capability. Common cases: It can also be a retention or legal-hold block. Check isRetention before retrying.

Symptom: 403 API_BUCKET_SCOPE_DENIED

The key is restricted to other buckets.
  • Compare the bucketId in the request with the bucket restriction shown in the dashboard.
  • Use an allowed bucket.
  • If the integration genuinely needs more buckets, update the key in the dashboard.
Do not create a second key to work around this without reviewing why the restriction exists.

Symptom: 403 API_KEY_SURFACE_DENIED

The route is not part of the storage surface. Sharing, audit, billing, tags, and administration routes are not available to API keys. Use a documented endpoint or perform the action in the dashboard.

Symptom: upload fails with 400

Fix the state; retrying the same request will not help.

Symptom: upload fails with 413

  • Trial accounts are capped at 100 MB per file.
  • Paid accounts are capped by plan.
Reduce the file size or upgrade. Pre-check size in your client before sending.

Symptom: upload fails with 402

Insufficient storage or inactive billing. Check stored size with GET /buckets/size/{bucketId}; the dashboard shows plan capacity.

Symptom: upload succeeds but the file is not where expected

  • Confirm which folder segment you used.
  • Check effectiveFolderId in the response.
  • A multi-file request returns only the first result; list the folder to find the rest.
  • A same-name upload may have created a version of an existing file rather than a new file. Check isUpdate.

Symptom: download is corrupt or truncated

If corruption persists, compare the SHA-256 of the downloaded bytes with your source.

Symptom: version endpoints return 200 but nothing happened

Version and restore endpoints nest a service result. Check data.status:
  • 404 — file or version missing,
  • 400 — already current, not in trash, or invalid key envelope,
  • 410 — restore window elapsed.

Symptom: 410 on restore

The trash display window has elapsed. The item is no longer restorable. The physical purge schedule is separate, but restore is no longer available.

Symptom: 429

Reduce concurrency, back off, and split workloads across keys. See Rate limits.

Symptom: CORS error in the browser

API key headers are not CORS-allowed. The preflight fails before the request reaches the API. Move the call to your backend.

Symptom: 5xx

The response body is sanitized in production. Collect:
  • timestamp with timezone,
  • route template,
  • HTTP status,
  • response code if any,
  • your request ID,
  • whether the operation was a read or a write.
For writes, verify state before retrying. Contact support if it persists.

What to send support

Include:
Never send the secret key, file contents, or full signed URLs.