---
id: status-codes
title: 'HTTP Status Codes Reference'
description: 'What each HTTP status actually means on the Agility API, with real response bodies'
sidebar_label: 'HTTP Status Codes'
sidebar_position: 3
tags: ['reference', 'http', 'errors']
---

What each status actually means on this API — with the codes you might
expect but will not meet. The companion guide is
[error handling](/guides/error-handling); when a `200` carries wrong data,
start at [troubleshooting](/troubleshooting).

## 200 OK — but Check the Body

`200` means the request was **understood**, not that everything worked:

- **`query.v1`** returns its array-of-arrays envelope — an empty inner
  array is a successful query with no matches, which is also what a
  too-strict filter or a [silently-repaired search](/reference/query-grammar)
  produces.
- **`api/asset`** returns `200` even when commands failed — the failures
  are itemised in `commandFailures`. **Check `commandFailures.count` on
  every response.** See
  [errors and partial failures](/apis/asset-bulk/errors).
- **`rest-1.v1`** creates, updates and operations all answer `200` with the
  asset (including the new moment OID). So do
  [webhook creations](/apis/webhooks/create).

## 400 Bad Request

A violation or a bad value, usually named in the body:

- **Violation tags** — `Violation'AssetCannotDeleteClosed`,
  `Violation'ClosedAssetCannotEditExistingValues`,
  `Violation'PrimaryWorkitemCannotHaveInvalidStatus` — many are
  [resolvable to readable text](/apis/conventions/errors#violation-tags-are-localizable)
- **Type errors** — `Wrong OID AssetType: Epic:3889` when a relation's
  value has the wrong type
- **Strict endpoints** — [`api/webhook`](/apis/webhooks/create) rejects
  unknown keys with a `400` and a message

### Query Parameter Errors {#query-parameter-errors}

A malformed value in a `rest-1.v1` query parameter returns `400` with a
`Message` naming the parameter, and a nested `Exception` carrying the detail
(such as `Unknown AttributeDefinition: Story.Bogus`):

- `Invalid SEL parameter`
- `Invalid WHERE parameter`
- `Invalid WITH parameter`
- `Invalid FIND or FINDIN parameter`
- `Invalid SORT parameter`
- `Invalid PAGE parameter`

## 401 Unauthorized

Three distinct causes, one code: missing/invalid credentials, an
Agility-issued token that was revoked, or **access tokens disabled
instance-wide**. The response carries a `WWW-Authenticate` challenge. See
[authentication errors](/getting-started/authentication#common-authentication-errors).

## 403 Forbidden

Authenticated, but the member's role lacks the right for that asset or
scope — see [roles and permissions](/reference/roles-and-permissions).

## 404 Not Found

No such route, or no such asset at a rest-1 URL. (A query for a nonexistent
asset is not a 404 — it is a `200` with an empty result set.)

## 405 Method Not Allowed

The wrong HTTP method for the route. The famous case:
[`api/customFields` is a POST](/apis/field-visibility/custom-fields), and a
`GET` gets a `405`.

## 500 Internal Server Error

On `api/asset`, a `500` almost always means **your body never parsed** —
malformed JSON/YAML, or well-formed input in an impossible shape (the
[sibling-alias trap](/apis/asset-bulk/aliases-and-projection#limitations)).
The response is opaque:

```json
{ "Exceptions": ["Server Error", "Reference: 76894036-5f86-49fd-bb4f-58970c644e2c"] }
```

Keep the reference GUID — it is the only handle support has. Full treatment:
[errors and partial failures](/apis/asset-bulk/errors).

## Codes You Might Expect but Will Not Meet

| Expected | Reality                                                                    |
| -------- | --------------------------------------------------------------------------- |
| `201`    | Creates return `200` with the asset — on rest-1, api/asset and api/webhook  |
| `204`    | Deletes are operations (`?op=Delete`) returning `200` with the asset        |
| `429`    | Returned when a request exceeds a [configured quota policy](/guides/rate-limiting): always a possibility on Digital.ai-hosted instances, and on-premises only where an administrator has enabled rate limiting. The body identifies which limit was exceeded and how long to wait before retrying; a `V1-Limit-Reason` header echoes the reason. Honor `RetryAfter` and back off |

## Related Topics

- [Error handling guide](/guides/error-handling)
- [Error conventions](/apis/conventions/errors)
- [Troubleshooting by symptom](/troubleshooting)
