# Errors

The API returns standard HTTP response codes to indicate success or failure of the API requests. For errors, we also return a customized error message inside the JSON response. You can see the returned HTTP status codes below.

| Code | Title | Description |
| --- | --- | --- |
| 200 | OK | The request message has been successfully processed, and it has produced a response. The response message varies, depending on the request method and the requested data. |
| 201 | Created | The request has been fulfilled and has resulted in one or more new resources being created. |
| 204 | No Content | The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. |
| 400 | Bad Request | The receiving server cannot understand the request because of malformed syntax. Do not repeat the request without first modifying it; check the request for errors, fix them and then retry the request. |
| 401 | Unauthorized | The request has not been applied because it lacks valid authentication credentials for the target resource. |
| 402 | Payment Required | Subscription data is incomplete or out of date. You'll need to provide payment details to continue. |
| 403 | Forbidden | You do not have the appropriate user rights to access the request. Do not repeat the request. |
| 404 | Not Found | The origin server did not find a current representation for the target resource or is not willing to disclose that one exists. |
| 409 | Conflict | The request could not be completed due to a conflict with the current state of the target resource. |
| 422 | Unprocessable Entity | The server understands the content type of the request entity, and the syntax of the request entity is correct but was unable to process the contained instructions. |
| 429 | Too Many Requests | You sent too many requests in a given amount of time ("rate limit"). Try again later. |
| 5xx | Server Errors | Something went wrong with the Unify API. These errors are logged on our side. You can contact our team to resolve the issue. |

## Transient errors

Any response with a `408`, `429`, or `5xx` status code is treated as
transient
 across every connector. Transient errors are usually caused by a temporary network blip, rate limit, or an outage on the downstream platform rather than a problem with your integration or credentials, so:

- They never invalidate the connection - you won't need to have your user reconnect.

- For reads, use bounded exponential backoff and respect available rate-limit headers. Check the SDK's retry configuration before adding an application-level retry loop.

A transient status does not prove that a write failed before changing the downstream system. After a timeout or server error on a create, update, or delete, inspect the request logs and read back the affected record before replaying it. If the outcome remains uncertain, stop for review. Do not assume that every connector supports idempotency keys. See the  [uncertain-write investigation](/guides/investigate-failed-request#other-outcomes-require-different-actions) .

A small number of connectors also treat specific error conditions as transient even though the downstream platform returns a "hard" status code like `400` or  `401` for them - for example, a vendor's own concurrent-request lockout. Where that applies, it's called out on that connector's Overview tab, for example  [QuickBooks](/apis/accounting/quickbooks).

## Error response format

Every Unified API error returns a JSON body with the same top-level fields, so you can branch on `type_name` instead of parsing the message.

| Field | Type | Description |
| --- | --- | --- |
| `status_code` | number | The HTTP status code of the response. |
| `error` | string | The standard reason phrase for the status code, for example "Bad Request". |
| `type_name` | string | A stable, machine-readable error type, such as `ConnectorExecutionError`. Each type is described below. |
| `message` | string | A short, human-readable summary. Do not parse it; it can change. |
| `detail` | string or object | Context for the specific error, such as the invalid fields, the unsupported filter or the downstream response. Its shape depends on `type_name`. |
| `ref` | string | A link to the section of this page that describes the `type_name`, for example `https://developers.apideck.com/errors#requestvalidationerror`. |

Here's a sample response for a request with an invalid body:

```
{
  "status_code": 400,
  "error": "Bad Request",
  "type_name": "RequestValidationError",
  "message": "Request Validation Error",
  "detail": {
    "errors": [
      {
        "message": "must be equal to one of the allowed values",
        "path": "request.body.status",
        "context": { "errorType": "enum" }
      }
    ]
  },
  "ref": "https://developers.apideck.com/errors#requestvalidationerror"
}
```

## Error types by HTTP status

Each `type_name` always maps to the same HTTP status, except connector and proxy errors, which pass the downstream status through.

| Status | type_name | What to do |
| --- | --- | --- |
| 400 | RequestValidationError, InvalidJsonPathError, UnsupportedFiltersError, MissingRequiredFiltersError, UnsupportedSortFieldError, UnsupportedPassThroughError, InvalidCursorError, ConnectionSettingsError, IdempotencyKeyInvalidError, IdempotencyKeyUnsupportedError | Fix the request using `detail`. Retrying it unchanged fails again. |
| 401 | UnauthorizedError, ConnectorCredentialsError, ConnectorDisabledError, IntegrationDisabledError | Check your API key, or ask your customer to reconnect or re-enable the connection in Vault. |
| 402 | RequestLimitError | Your plan's request limit is reached. Upgrade or wait for the limit to reset. |
| 403 | CONSENT_REQUIRED, RESOURCE_NOT_CONSENTED, INVALID_CONSENT, UNKNOWN_CONSENT | The connection's data scopes do not allow this request. See  [data scope errors](#data-scope-errors). |
| 404 | EntityNotFoundError, NotFoundError, IntegrationNotFoundError, ConnectorNotFoundError | Check the record ID, the service ID and that the integration is enabled. |
| 409 | UniqueConstraintError, IdempotencyKeyInProgressError | The record already exists, or a request with the same idempotency key is still running. |
| 422 | FIELD_NOT_CONSENTED, PlanDowngradeError, VirtualWebhooksWebhookRequiredError, IdempotencyKeyMismatchError | The request is valid but cannot be processed in the current state. |
| 429 | ConnectorRateLimitError | The downstream platform rate-limited the request. See  [rate limits](#rate-limits). |
| 501 | MappingError, ConnectorMappingNotFoundError, ConnectorResponseMappingNotFoundError, ConnectorOperationMappingNotFoundError, ConnectorOperationUnsupportedError, ConnectorWorkflowMappingError, PaginationNotSupportedError, CustomFieldsNotSupportedError, SchemaNotSupportedError | The connector does not support this operation or field. Check the connector's coverage before retrying. |
| 503 | IdempotencyStoreUnavailableError | Retry the request with the same idempotency key after a short backoff. |
| Downstream status | ConnectorExecutionError, VaultConnectionRefreshError, ProxyTimedOutError, ProxyDownstreamTimedOutError, ProxyConnectionResetError | The status the downstream platform returned (400 if it returned none). See  [ConnectorExecutionError](#connectorexecutionerror). |
| 500 | UnexpectedError and any other type | Apideck logs these. Contact support with the request time and consumer ID. |

OAuth authorization errors (`OAuthCredentialsNotFoundError`,  `OAuthRedirectUriError`, `OAuthInvalidStateError`,  `OAuthCodeExchangeError` and others) redirect the user back to your redirect URL when one is available, and otherwise return a JSON error.

## Deciding whether to retry

When a connector call fails at the network level (a DNS failure, a timeout or a reset connection), `detail` also contains `reason` and  `retriable`:

- `retriable: true`: the failure happened in transport and the operation is safe to repeat with backoff.

- `retriable: false` with `outcome: "uncertain"`: a create timed out and may have been written downstream. Read the record back before retrying, or you can create a duplicate.

## Rate limits

A downstream `429` returns `ConnectorRateLimitError` with status  `429`. For connectors whose rate-limit headers Apideck maps, the response also carries `x-downstream-ratelimit-limit`,  `x-downstream-ratelimit-remaining` and `x-downstream-ratelimit-reset`; for some of them the reset value comes from the platform's `Retry-After`. Not every connector exposes these headers. When `x-downstream-ratelimit-reset` is present, wait until then; otherwise use bounded exponential backoff with jitter. See  [rate limits](/guides/unified-rate-limits) for details.

## Proxy API errors

The [Proxy API](/apis/proxy/reference) returns the downstream platform's response unchanged, including its status code and body. When that response is an error, Apideck adds the header `x-apideck-downstream-error: true` so you can tell a downstream error from an Apideck one. Proxy responses also carry an `x-apideck-request-id` header you can quote to support. Proxy timeouts and resets return `ProxyTimedOutError`,  `ProxyDownstreamTimedOutError` or `ProxyConnectionResetError`.

## Handling errors

The Unify API and SDKs can produce errors for many reasons, such as a failed requests due to misconfigured integrations, invalid parameters, authentication errors, and network unavailability. Use [Logs](/logs) to see the request Apideck sent to the connector and the response it received.

## Error Types

### RequestValidationError

The request does not match the OpenAPI specification. Check the spelling and types of your attributes, and make sure you are not sending fields outside the specification. The fields that failed are listed in `detail`.

### MissingParamsError

An authorization request is missing required parameters. The missing parameters are described in `detail`.

### ConnectorExecutionError

A Unified API request made through a downstream connector returned an error. The downstream  `status_code` is passed through to the response, and the downstream response is in `detail`:

- `detail.statusCode`: the HTTP status the downstream platform returned.

- `detail.context`: the `connector`, `unified_api`,  `resource` and `action` of the failed call.

- `detail.error`: the downstream response body, parsed as JSON when possible.

- `detail.responseHeaders`: the headers of the downstream response.

- `detail.reason`, `detail.retriable` and `detail.outcome`: present for network failures. See  [deciding whether to retry](#retriable-errors).

For some connectors, `downstream_errors` consolidates the downstream errors into a consistent list.

Here's a sample response:

```
{
  "status_code": 400,
  "error": "Bad Request",
  "type_name": "ConnectorExecutionError",
  "message": "Xero Connector Returned Error",
  "downstream_errors": [
    {
      "code": 100,
      "message": "Invoice # must be unique.",
      "detail": "The invoice number must be unique."
    }
  ],
  "detail": {
    "statusCode": 400,
    "responseHeaders": {},
    "context": {
      "connector": "Xero",
      "unified_api": "accounting",
      "resource": "invoices",
      "action": "add"
    },
    "error": {}
  },
  "ref": "https://developers.apideck.com/errors#connectorexecutionerror"
}
```

### UnauthorizedError

We were unable to authorize the request as made. This can happen for a number of reasons, from missing header params to passing an incorrect authorization token. Verify your Api Key is being set correctly in the authorization header. ie:  `Authorization: 'Bearer sk_live_***'`. A user may disconnect your application by revoking access from within their connected platform UI. Your application should handle the "401 error" and allow the user to reconnect/reauthorize the integration quickly.

### ConnectorCredentialsError

A request using a given connector has not been authorized. Ensure the connector you are trying to use has been configured correctly and been authorized for use.

### ConnectorDisabledError

A request has been made to a connector that has since been disabled. This may be temporary. You can contact our team to resolve the issue.

### IntegrationDisabledError

The integration is disabled for your application or for this consumer's connection. Enable it in the Apideck dashboard, or ask your customer to re-enable it in Vault.

### ConnectorRateLimitError

The downstream platform rate-limited the request. Rate limits vary from connector to connector. See [rate limits](#rate-limits) for the headers to use when retrying.

### RequestLimitError

You have reached the number of requests included in your subscription. You will not be able to make further requests until this limit resets, or talk to us about upgrading your subscription to continue immediately.

### EntityNotFoundError

You've made a request for a resource or route that does not exist. Verify your path parameters or any identifiers used to fetch this resource.

### NotFoundError

The requested route or resource does not exist.

### IntegrationNotFoundError

The requested connector integration could not be found associated to your  `application_id`. Verify your `application_id` is correct, and that this connector has been added and configured for your application.

### ConnectorNotFoundError

A request was made for an unknown connector. Verify your `service_id` is spelled correctly, and that this connector is enabled for your provided `unified_api`.

### InvalidJsonPathError

A JSON path in the request, for example in `pass_through` or field mapping, is not valid. The path is described in `detail`.

### UnsupportedFiltersError

The connector does not support one or more of the filters you sent. The unsupported filters are listed in `detail`.

### MissingRequiredFiltersError

The connector requires a filter that was not sent for this request. The required filters are listed in `detail`.

### UnsupportedSortFieldError

The connector cannot sort by the field you requested. The supported sort fields are listed in `detail`.

### InvalidCursorError

The pagination cursor is invalid or expired. Start the listing again from the first page.

### ConnectionSettingsError

The connection is missing settings the connector needs, for example a required company or tenant ID. Ask your customer to complete the connection settings in Vault.

### UniqueConstraintError

A record with the same unique value already exists.

### Idempotency key errors

`IdempotencyKeyInvalidError` (400): the key is not valid.  `IdempotencyKeyUnsupportedError` (400): the operation does not support idempotency keys. `IdempotencyKeyInProgressError` (409): a request with this key is still running. `IdempotencyKeyMismatchError` (422): the key was used before with a different request body. `IdempotencyStoreUnavailableError` (503): retry with the same key after a short backoff.

### Data scope errors

When a connection uses [data scopes](/guides/data-scopes-for-accounting),  `CONSENT_REQUIRED`, `RESOURCE_NOT_CONSENTED`,  `INVALID_CONSENT` and `UNKNOWN_CONSENT` return `403`, and  `FIELD_NOT_CONSENTED` returns `422` when you write a field the connection has no write permission for.

### PlanDowngradeError

The change is not allowed on your current plan.

### VirtualWebhooksWebhookRequiredError

Virtual webhooks need an enabled webhook subscription for the Unified API before they can be activated. Create a [webhook subscription](/guides/webhooks) first.

### VaultConnectionRefreshError

Refreshing the connection's access token failed. The downstream status is passed through. If it persists, ask your customer to reconnect the integration in Vault.

### MappingError

There was an error attempting to retrieve the mapping for a given attribute. We've been notified and are working to fix this issue.

### ConnectorMappingNotFoundError

It seems the implementation for this connector is incomplete. It's possible this connector is in `beta` or still under development. We've been notified and are working to fix this issue.

### ConnectorResponseMappingNotFoundError

We were unable to retrieve the response mapping for this connector. It's possible this connector is in `beta` or still under development. We've been notified and are working to fix this issue.

### ConnectorOperationMappingNotFoundError

Connector mapping has not been implemented for the requested operation. It's possible this connector is in `beta` or still under development. We've been notified and are working to fix this issue.

### ConnectorOperationUnsupportedError

The connector does not support this operation. Check the connector's coverage for the operations it supports.

### ConnectorWorkflowMappingError

The composite api calls required for this operation have not been mapped entirely. It's possible this connector is in `beta` or still under development. We've been notified and are working to fix this issue.

### PaginationNotSupportedError

The connector does not support pagination for this resource.

### CustomFieldsNotSupportedError

The connector does not support custom fields for this resource.

### SchemaNotSupportedError

The connector does not expose a schema for this resource.

### ProxyTimedOutError

The request to the downstream platform timed out. For creates, read the record back before retrying; see [deciding whether to retry](#retriable-errors).

### ProxyDownstreamTimedOutError

The downstream platform did not respond in time.

### ProxyConnectionResetError

The downstream platform closed the connection before responding.

### UnexpectedError

An unexpected error occurred. Apideck logs these. Contact support with the request time and consumer ID if it persists.

### OAuthCredentialsNotFoundError

When adding a connector integration that implement OAuth, both a `client_id` and  `client_secret` must be provided before any authorizations can be performed. Verify the integration has been configured properly before continuing.

### OAuthRedirectUriError

A request was made either in a connector authorization flow, or attempting to revoke connector access without a valid `redirect_uri`. This is the url the user should be returned to on completion of process.

### OAuthInvalidStateError

The state param is required and is used to ensure the outgoing authorization state has not been altered before user id redirected back. It also contains required params needed to identify the connector being used. If this has been altered, the authorization will not succeed.

### OAuthCodeExchangeError

When attempting to exchange the authorization code for an `access_token` during an OAuth flow, an error occurred. This may be temporary. You can reattempt authorization or contact our team to resolve the issue.

### UnsupportedPassThroughError

A `pass_through` value could not be applied because the connector sends an XML request body (SOAP connectors such as NetSuite, Sage Intacct and Workday). Adding a value at the root of the request would place it outside the XML document element and produce a request the connector cannot serialize, so it is refused rather than sent. The offending keys are listed in `detail.unsupported_pass_through_keys`. Use an  `extend_paths` entry whose path starts at the document element named in  `detail.xml_document_element` to set a value inside the document — see  [Pass Through](/guides/pass-through#xml-and-soap-connectors).
