> For the complete documentation index, see [llms.txt](https://docs.material.security/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.material.security/reference/api-v1/errors-and-troubleshooting.md).

# Errors and Troubleshooting

## Logs

API events are logged in the [Audit Log](https://docs.material.security/learn-more/administration/audit-log). API related events are indicated next to the Actor with the API icon:

<figure><img src="https://3441929823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDXSwW7QZtKgywlqSARjL%2Fuploads%2FkGh3Kw80dZ6DADMcsrOQ%2Fimage.png?alt=media&amp;token=fd9df927-fb8e-40ae-9087-ded3a843dedf" alt="" width="204"><figcaption></figcaption></figure>

***

API related events are listed in the Audit Log. You can also quickly navigate to token specific events via the tokens list:

1. From **Tokens**, select **one** token row.
2. Click **View Audit Events.**
3. The Audit Log opens, pre-filtered to this token's events within the last week. Update the filter as needed.

<figure><img src="https://3441929823-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDXSwW7QZtKgywlqSARjL%2Fuploads%2FCSNt8i4Hcbk9uE7TcHjp%2Fimage.png?alt=media&amp;token=def90658-4eb3-49c0-bf84-7bbdecc015aa" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
The filtered audit log shows results for a single token. Since accounts can have multiple tokens, it may not include all events for a given user.
{% endhint %}

***

## Error responses

Every endpoint returns the same error shape: a JSON body with an `error` field describing what went wrong.

| Status                      | Meaning                                                        | What to check                                                                                                  |
| --------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`           | A parameter or request body failed validation                  | The response includes a `validationFailures` array naming each field that failed.                              |
| `401 Unauthorized`          | The API token is missing or invalid                            | The `x-material-client-secret` header is present and the token is correct.                                     |
| `403 Forbidden`             | The token is valid, but the account behind it lacks permission | The account's roles. Some endpoints need more than read access, and a few check a per-account setting.         |
| `404 Not Found`             | The resource doesn't exist, or your token can't reach it       | The encoded ID, and whether the resource belongs to a tenant your token can access                             |
| `429 Too Many Requests`     | You've reached the rate limit on an endpoint that has one      | Wait the number of seconds in the `Retry-After` header, then retry. See [Rate limiting](#rate-limiting) below. |
| `500 Internal Server Error` | Something failed on Material's side                            | Retry, then contact support if it persists.                                                                    |

A `403` doesn't always mean your token is under-scoped. Two cases are worth knowing:

* Requesting `include=investigation` on an OAuth app needs permission to read investigation data on top of app access. Without it you get a `403` rather than a response with the field quietly missing, so a null value always means there's nothing to show.
* Revoking an account's grant of an OAuth app returns `403` when OAuth App Remediation is turned off for that account. That's a per-account setting, not a property of your token.

***

## Rate limiting

Some endpoints are rate limited to protect your instance. When you reach a limit, the endpoint returns `429 Too Many Requests` with a `Retry-After` header giving the number of seconds to wait before you try again.

| Endpoint                                                                                                                                                      | How the limit is counted                                                                 | When it resets         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------- |
| [Search Messages](https://docs.material.security/reference/api-v1/messages#post-api-v1-messages-search) (`POST /api/v1/messages/search`)                      | Days searched: each search uses one unit for every day its date range covers             | Daily, at midnight UTC |
| [Move Messages to Inbox](https://docs.material.security/reference/api-v1/messages#post-api-v1-messages-move-to-inbox) (`POST /api/v1/messages/move-to-inbox`) | The number of messages a request targets, shared across every token in your organization | After a short wait     |

The Search Messages limit applies only if your instance has a daily search budget. When it does, both successful and rate-limited responses include these headers, so you can track your usage as you go:

* `X-RateLimit-Limit`: your daily budget, in days searched
* `X-RateLimit-Remaining`: how much of the budget is left
* `X-RateLimit-Reset`: when the budget resets, as a Unix timestamp in seconds

A rejected search doesn't use any of your budget, so a search with a shorter date range can still go through.

Build retries into any script that runs at volume. When you receive a `429`, wait for the time in `Retry-After`, then retry rather than continuing at the same rate. A `429` doesn't mean anything is wrong with your token.

{% hint style="warning" %}
Before version 1.64, Search Messages returned `400 Bad Request` when you reached the limit. If your integration checks for a `400` to detect the limit, update it to handle `429`.
{% endhint %}

{% hint style="info" %}
The [Material MCP server](https://docs.material.security/reference/material-mcp-server) is rate limited separately, with its own limit and its own error format. See [Material MCP Server](https://docs.material.security/reference/material-mcp-server) for details.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.material.security/reference/api-v1/errors-and-troubleshooting.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
