Error Codes
Comprehensive reference for all error codes returned by the Texture REST API
Error Response Structure#
All error responses from the Texture REST API return a JSON body with at minimum a code and message field:
{
"code": "ERROR_CODE",
"message": "Human-readable description of the error"
}| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code. Use this for programmatic error handling. |
message | string | Human-readable description. Use for logging — do not parse for control flow, as wording may change. |
Additional Fields#
Some error responses include extra fields alongside code and message:
| Field | Type | When Present | Description |
|---|---|---|---|
details | object | Validation errors | Contains field-level error information |
mismatchedFields | string[] | PARAMETER_MISMATCH only | Lists which fields differ from the existing resource |
retryAfter | number | RATE_LIMITED only | Seconds until rate limit window resets (also in Retry-After header) |
Example: Standard Error#
{
"code": "DEVICE_NOT_FOUND",
"message": "The specified device does not exist"
}Example: Validation Error with Details#
{
"code": "VALIDATION_ERROR",
"message": "The request body failed validation",
"details": {
"serialNumber": "Serial number is required",
"capacity": "Must be a positive number"
}
}Example: Rate Limit Error#
{
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again later.",
"retryAfter": 42
}Example: Conflict with Mismatched Fields#
{
"code": "PARAMETER_MISMATCH",
"message": "A device with this manufacturer device ID already exists with different parameters",
"mismatchedFields": ["serialNumber", "name"]
}Authentication Errors (401)#
Returned when the API cannot verify the caller's identity.
| Error Code | Description | What to Do |
|---|---|---|
UNAUTHENTICATED | Missing, invalid, expired, or revoked API key | Verify your API key is included, correctly formatted, and active. Generate a new key in the Dashboard if needed. |
Common causes#
- Missing
Texture-Api-Keyheader - Malformed API key value
- API key has been revoked or expired
- Using the wrong API key type for the endpoint (e.g., using a Management key on an OEM endpoint that requires a Manufacturer key)
Do not retry. Fix the API key and re-send.
Authorization Errors (403)#
Returned when the API key is valid but lacks permission for the requested operation.
| Error Code | Description | What to Do |
|---|---|---|
FORBIDDEN | Insufficient permissions for this resource or action | Verify the key's scopes include the resource type and operation you're attempting |
DEVICE_MODEL_MANUFACTURER_MISMATCH | The device model belongs to a different manufacturer than your API key | Confirm your Manufacturer API key matches the device model's manufacturer |
DEVICE_NOT_OEM_DIRECT | The device was not provisioned via OEM Direct | Only OEM Direct devices can receive telemetry via POST /devices/:id/telemetry |
MANUFACTURER_NOT_ALLOWED | The device's manufacturer is not in your API key's scope | Check that your Manufacturer API key is scoped to the correct manufacturer |
Do not retry. Adjust your API key permissions or correct the request.
Validation Errors (400)#
Returned when the request data is invalid or the operation cannot be performed given the resource's current state.
| Error Code | Description | What to Do |
|---|---|---|
VALIDATION_ERROR | Required fields missing or invalid. The details field lists specific field errors. | Read the details object, fix the indicated fields, and retry |
INVALID_LOCATION | The provided address or coordinates could not be resolved to a valid location | Verify the address is correctly formatted and geocodable |
INVALID_STATE | The operation is not valid for the resource's current state | Check the resource's current state; some operations are only valid in certain lifecycle stages |
INVALID_STATUS | The requested status transition is not allowed | Consult the API docs for valid status transitions |
INVALID_CRITERIA | The filter or query criteria are malformed | Check filter syntax and supported operators |
CUSTOMER_NOT_CONNECTED_TO_SITE | The customer is not associated with the specified site | Verify the customer-site relationship before performing this operation |
DELETION_PROTECTION_ENABLED | Workspace has deletion protection enabled | Disable deletion protection before retrying |
SITE_ALREADY_EXISTS | A site with this address already exists in the workspace | Use the existing site or provide a different address |
DUPLICATE_NAME | A resource with this name already exists in the same scope | Choose a different name |
DEVICE_MODEL_NOT_FOUND | The specified deviceModelId does not match any known device model | Verify the device model ID; use the device models endpoint to list available models |
Do not retry without modifying the request. Read the message and details fields to identify what needs to change.
Resource Not Found Errors (404)#
Returned when the specified resource does not exist or is not accessible with your current API key.
| Error Code | Description |
|---|---|
NOT_FOUND | The requested resource does not exist |
CUSTOMER_NOT_FOUND | The specified customer ID does not exist |
DEVICE_NOT_FOUND | The specified device ID does not exist |
SITE_NOT_FOUND | The specified site ID does not exist |
SITE_NOT_IN_WORKSPACE | The site exists but is not accessible from your current workspace scope |
APIKEY_NOT_FOUND | The specified API key ID does not exist |
WORKSPACE_NOT_FOUND | The specified workspace ID does not exist |
SCHEDULE_NOT_FOUND | The specified schedule ID does not exist |
DEVICE_NOT_ASSOCIATED | The device exists but is not associated with any workspace |
COLLECTION_NOT_FOUND | The specified collection ID does not exist |
Verify the resource ID is correct. The resource may have been deleted, or your API key may not have access to the workspace that contains it.
Conflict Errors (409)#
Returned when the request conflicts with the current state of an existing resource.
| Error Code | Description | What to Do |
|---|---|---|
DUPLICATE_CONNECTION | A connection with these parameters already exists | Use the existing connection instead of creating a duplicate |
PARAMETER_MISMATCH | A device with the same manufacturerDeviceId exists with different attribute values | Either update the existing device or correct the conflicting fields in your request |
Handling PARAMETER_MISMATCH#
This error is specific to OEM device creation (POST /devices). When you create a device and one with the same manufacturerDeviceId already exists, the API compares fields. If they all match, the call succeeds idempotently. If any fields differ, you receive PARAMETER_MISMATCH with a mismatchedFields array listing the differing fields.
Rate Limit Errors (429)#
Returned when the caller exceeds the API's request rate limits.
Rate Limit Response Headers#
| Header | Type | Description |
|---|---|---|
X-RateLimit-Limit | number | Maximum requests allowed per window |
X-RateLimit-Remaining | number | Requests remaining in the current window |
X-RateLimit-Reset | number | Unix timestamp (seconds) when the window resets |
Retry-After | number | Seconds until you can retry |
Rate Limits by Operation Type#
| Operation Type | Limit |
|---|---|
| Read operations (GET) | 300 requests/minute |
| Write operations (POST, PATCH, PUT, DELETE) | 60 requests/minute |
Rate limits are applied per API key. Wait for the number of seconds in Retry-After, then retry. For sustained rate limiting, implement exponential backoff.
Server Errors (500, 502)#
Returned when an unexpected error occurs on the server side. These are never caused by your request data.
| HTTP Status | Error Code | Description |
|---|---|---|
| 500 | UNKNOWN_ERROR | An unexpected error occurred while processing the request |
| 500 | LOCATION_SERVICE_ERROR | The address validation service is temporarily unavailable |
| 502 | SERVICE_UNAVAILABLE | A dependent service is temporarily unreachable |
Retry with exponential backoff (1s → 2s → 4s). After 3–5 retries, stop and contact Texture support.
OEM Device Integration Errors#
Quick reference for OEM Direct Integration endpoints.
Device Creation — POST /devices#
| Error Code | HTTP | Description | What to Do |
|---|---|---|---|
VALIDATION_ERROR | 400 | Required fields missing or invalid | Check details for field-level errors |
DEVICE_MODEL_NOT_FOUND | 400 | The deviceModelId does not match any known model | Verify the device model ID |
SITE_NOT_FOUND | 404 | The specified siteId does not exist | Verify the site ID |
DEVICE_MODEL_MANUFACTURER_MISMATCH | 403 | The device model belongs to a different manufacturer | Use a model belonging to your manufacturer |
PARAMETER_MISMATCH | 409 | Device with same manufacturerDeviceId exists with different attributes | See Conflict Errors section |
If you create a device with a manufacturerDeviceId that already exists and all fields match, the request succeeds and returns the existing device. This allows safe retries.
Telemetry Push — POST /devices//telemetry#
| Error Code | HTTP | Description | What to Do |
|---|---|---|---|
DEVICE_NOT_FOUND | 404 | The device ID does not exist | Verify the device ID |
DEVICE_NOT_OEM_DIRECT | 403 | The device was not provisioned via OEM Direct | This endpoint only accepts telemetry for OEM Direct devices |
MANUFACTURER_NOT_ALLOWED | 403 | The device's manufacturer is not in your API key's scope | Verify your Manufacturer API key scope |
DEVICE_NOT_ASSOCIATED | 404 | The device is not associated with any workspace | Device must be associated with a workspace before telemetry can be ingested |
VALIDATION_ERROR | 400 | The telemetry payload is invalid or missing required fields | Check details for field-level errors |
HTTP Status Code Quick Reference#
| Status | Meaning | Retryable? | Action |
|---|---|---|---|
| 400 | Bad Request | No | Fix request data per code, message, and details |
| 401 | Unauthenticated | No | Fix or replace API key |
| 403 | Forbidden | No | Check API key scopes and permissions |
| 404 | Not Found | No* | Verify resource ID and workspace access |
| 409 | Conflict | No | Resolve the conflict per the error details |
| 429 | Too Many Requests | Yes | Wait for Retry-After, then retry |
| 500 | Internal Server Error | Yes | Retry with exponential backoff |
| 502 | Service Unavailable | Yes | Retry with exponential backoff |
* 404 may be retryable if the resource was very recently created (eventual consistency). A single retry after 1–2 seconds is reasonable.
Best Practices for Error Handling#
- Branch on HTTP status code first. Use the status code to determine the error category, then inspect
codefor specifics. - Use
codefor programmatic handling. Thecodefield is stable and machine-readable. Map code values to specific handling logic in your client. - Use
messagefor logging only. Themessagefield is human-readable and may change without notice. Do not parse it for control flow. - Retry only retryable errors. Only 429, 500, and 502 responses should be retried. All other status codes indicate a problem with the request itself.
- Respect
Retry-After. When present, always honor theRetry-Afterheader before retrying. - Implement exponential backoff for server errors. Start at 1 second and double on each retry, up to a maximum of 3–5 attempts.
- Log the full error response. Always log
code,message, and any additional fields (details,mismatchedFields) for debugging. - Handle
PARAMETER_MISMATCHexplicitly in your device provisioning flow. This is an expected response when re-provisioning devices and should be handled as a recoverable conflict, not a generic error. - Monitor rate limit headers proactively. Check
X-RateLimit-Remainingon successful responses to throttle your request rate before hitting 429.