Documentation Index
Fetch the complete documentation index at: https://developer.box.com/llms.txt
Use this file to discover all available pages before exploring further.
When your Box application returns an unexpected error, fails intermittently, or stops processing requests, you need a structured workflow for finding the root cause. This guide walks you through one: how to read a Box error response, when and how to retry, how to set sensible timeouts, and which Box-provided tools to use at each step.
Take a systematic approach
Most Box API failures come from one of a small number of causes: an invalid token, a missing scope, an item the app cannot access, a malformed request, or a transient server-side issue. Before you change code, break the failing flow into smaller, independently testable parts:
- Authentication. Can your app obtain an access token? Is the token the right type for your auth method (OAuth 2.0, JWT, or Client Credentials Grant)?
- Authorization. Does the token have the scopes the endpoint requires? Does the service account or user have access to the target item?
- Request construction. Is the URL, HTTP method, header set, and body exactly what the API reference specifies?
- Server response. What HTTP status code and Box error code came back? Was the request retried correctly if it was transient?
- Downstream side effects. If you call other systems from a webhook or worker, did they succeed?
Test each step in isolation with a tool such as curl or Postman before you dig into application code.
Inspect the API response
Box returns a structured error object for most 4xx and 5xx responses. Always log the full response body and the response headers — they are the single most useful piece of evidence you can collect.
{
"type": "error",
"status": 403,
"code": "access_denied_insufficient_permissions",
"help_url": "https://developer.box.com/guides/api-calls/permissions-and-errors/common-errors/",
"message": "Access denied - insufficient permission",
"request_id": "abcdef123456"
}
Use the fields as follows:
| Field | What to do with it |
|---|
status | The HTTP status code. Tells you the broad category (auth, permission, not found, rate limit, server error). |
code | The Box-specific error code. Map this to a fix using the . |
message | A human-readable description. Often contains the specific field or value that failed validation. |
help_url | A direct link to documentation for the error. |
request_id | A unique identifier for the failed request. Include this in any support ticket. |
Most Box API responses also include a box-request-id response header. This is a different value from the request_id field in the error body. Capture both when you can.
For the full catalog of Box error codes by HTTP status, see .
Handle retries and timeouts
Not every failure is permanent. The right response to a transient error is to retry; the right response to a permanent error is to stop and surface it to the caller. Retrying a permanent error wastes quota and can amplify outages.
Which responses to retry
| Status code | Retry? | Notes |
|---|
408 Request Timeout | Yes | The request did not reach the server in time. Retry with the same payload. |
429 Too Many Requests | Yes | You have been rate limited. Honor the retry-after header. See . |
500 Internal Server Error | Yes | Transient. Use exponential back-off. |
502 Bad Gateway | Yes | Transient. Use exponential back-off. |
503 Service Unavailable | Yes | Honor the retry-after header when present. Check the Box status page if it persists. |
4xx (other) | No | These indicate a problem with the request itself. Fix the request before resending. |
Use exponential back-off with jitter
When you retry, increase the wait between attempts so you do not pile retries on top of a service that is already struggling. A simple pattern: wait base * 2^attempt seconds, capped at a maximum, plus a small random delay (jitter) to avoid thundering-herd retries from parallel workers.
import random, time
def backoff_seconds(attempt: int, base: float = 1.0, cap: float = 60.0) -> float:
delay = min(cap, base * (2 ** attempt))
return delay + random.uniform(0, delay * 0.1)
When the response includes a retry-after header, wait at least that many seconds before retrying instead of using your own back-off value.
Set sensible request timeouts
Long-lived requests tie up workers and hide failures. Set an explicit timeout on every HTTP call your app makes to Box, and let the timeout fire a retry rather than waiting indefinitely. Choose values that match the endpoint: small JSON reads can use short timeouts, while uploads and AI extract calls need longer windows. If you use a Box SDK, automatic retries and exponential back-off are already built in.
Make retries safe
Retrying a GET is always safe. Retrying a POST, PUT, or DELETE can create duplicates if the original request actually succeeded but the response was lost. To make those retries safe:
- For chunked uploads, reuse the existing upload session and re-upload only the affected part. See .
- Treat a
409 item_name_in_use on a retried create as “the original request already succeeded” rather than a real conflict, when that matches your flow. For example, if you retry POST /files/content and receive item_name_in_use, list the parent folder and look up the file you just tried to upload — in most cases the first attempt persisted before the response was lost.
- Before retrying a non-
GET request, check whether the resource already exists. For example, before re-uploading a file, call GET /folders/:id/items on the destination folder and compare file names and sizes; before re-creating a collaboration, call GET /folders/:id/collaborations.
When you cannot reproduce a problem locally, or you need to see exactly what Box recorded for a request, run an from the Developer Console.
The report exports a .csv of every API call your application made in a chosen 24-hour window. For each call it includes:
- The HTTP status code Box returned.
- The API request duration.
- The
API Request ID — give this to Box Support and they can look up the exact request.
- The resource, sub-resource, HTTP method, and timestamp.
Use the App Diagnostics Report when you need to:
- Confirm whether a request ever reached Box.
- Find the request ID for a failed call that your own logs missed.
- Compare call volume against your expected pattern (for example, to see whether retries are running away).
- Provide Box Support with the precise call they need to investigate.
The App Diagnostics Report does not include API calls made in the last 48 hours, or authorization and token API calls. For real-time investigations, rely on your application logs first.
For step-by-step setup instructions, see .
Capture the request ID for Box Support
If you need to escalate to Box Support, include the full Box error response and at least one of:
- The
request_id value from the error response body.
- The
box-request-id response header from the failed call.
- The
API Request ID column from an App Diagnostics Report.
With one of these IDs, Box Support can locate the exact request on the server side. Without one, investigating a single failure across millions of daily API calls is much slower.
Debug common scenarios
The following checklist covers the failure modes most apps hit first.
Authentication and token issues
| Symptom | First check |
|---|
401 invalid_token | The token expired or was revoked. Refresh it, or request a new one. See . |
400 invalid_grant with “Current date time must be before the expiration date time” | The clock on the host running your app is out of sync with NTP. Re-sync time. |
400 invalid_client | The client_id or client_secret in your token request does not match the values in the Developer Console. |
400 unauthorized_client | A JWT or CCG application has not been authorized by the enterprise admin. See . |
For UI-side authorization errors (admin console messages), see .
Permission and access issues
| Symptom | First check |
|---|
403 access_denied_insufficient_permissions | The user or service account does not have access to the item, or your app is missing the required scope. Confirm the item is shared with the service account if you use CCG or JWT. |
403 insufficient_scope | The application scopes in the Developer Console do not include the one this endpoint needs. See . |
404 not_found on an item you can see in the web app | Your token belongs to a different user (often the service account) that has not been invited to the item. |
Rate limit and capacity issues
| Symptom | First check |
|---|
429 rate_limit_exceeded | Honor the retry-after header and back off. Review which limit you are hitting in . |
| Latency spikes plus 5xx | Check the Box status page for known incidents. Add exponential back-off if you have not already. |
Webhook issues
| Symptom | First check |
|---|
| Webhooks never arrive | Confirm the target URL is publicly reachable over HTTPS and returns 2xx to a test POST. Check that the webhook is scoped to the correct trigger and item. |
| Webhooks arrive but processing fails | Log the full payload, then replay it against your handler. Verify the signature before processing in production. See . |
Check the Box status page
If multiple unrelated calls start failing with 5xx errors, before you dig into your own code, check status.box.com for a known incident. When Box has an active incident, the right action is usually to back off and let the existing retry logic ride it out.
Next steps
- Review the full catalog of error codes in .
- Tune your retry policy against the limits in .
- Run an the next time you see an unexpected failure.