Skip to main content
The Dakota API uses RFC 9457 Problem Details for all error responses. This standardized format provides machine-readable error types, human-readable descriptions, and actionable details to help you handle errors programmatically.

Error Response Format

All errors return a JSON response with the application/problem+json content type:
{
  "type": "not-found",
  "title": "Customer Not Found",
  "status": 404,
  "detail": "Customer cst_2abc123 was not found in your organization.",
  "instance": "/customers/cst_2abc123",
  "request_id": "req_7f3a8b2c"
}

Response Fields

FieldTypeRequiredDescription
typestringYesMachine-readable error type identifier.
titlestringYesShort, human-readable summary. Stable across occurrences of the same error type.
statusintegerYesHTTP status code for this occurrence.
detailstringNoHuman-readable explanation specific to this occurrence.
instancestring (URI)NoThe request path that triggered this error.
request_idstringNoUnique request identifier. Include this when contacting support.
errorsarrayNoField-level validation errors (present only for validation failures).

Validation Errors

When a request fails validation, the response includes an errors array with field-level details:
{
  "type": "validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "One or more fields failed validation.",
  "instance": "/customers",
  "request_id": "req_8d4b2e1f",
  "errors": [
    {
      "field": "bank_account.routing_number",
      "message": "Routing number must be exactly 9 digits",
      "code": "invalid_format"
    },
    {
      "field": "email",
      "message": "Invalid email address format",
      "code": "invalid_format"
    }
  ]
}
Validation Error Fields:
FieldTypeRequiredDescription
fieldstringYesField path using dot notation for nested fields (e.g., bank_account.routing_number).
messagestringYesHuman-readable description of the field error.
codestringNoMachine-readable error code for this specific field.

HTTP Status Codes

Status CodeCategoryDescription
200SuccessRequest completed successfully
201SuccessResource created successfully
204SuccessRequest succeeded with no response body
400Client ErrorInvalid request parameters, body, or identifiers
401Client ErrorMissing or invalid authentication credentials
403Client ErrorValid credentials but insufficient permissions
404Client ErrorResource does not exist
409Client ErrorResource conflict or state conflict
413Client ErrorRequest payload exceeds maximum allowed size
422Client ErrorRequest blocked due to compliance restrictions
429Client ErrorRate limit exceeded
500Server ErrorInternal server error
501Server ErrorEndpoint not implemented
502Server ErrorUpstream provider error
503Server ErrorService temporarily unavailable

Error Types Reference

Each error type has a unique URI that identifies the problem category. The type field in every error response links directly to the corresponding section below.

Client Errors (4xx)

HTTP Status: 400 Bad RequestDescription: One or more request fields failed validation. Check the errors array for specific field-level details.Example Response:
{
  "type": "validation-error",
  "title": "Validation Error",
  "status": 400,
  "detail": "One or more fields failed validation.",
  "instance": "/accounts/onramp",
  "request_id": "req_abc123",
  "errors": [
    {
      "field": "capabilities",
      "message": "capabilities is required",
      "code": "required"
    }
  ]
}
Common Causes:
  • Missing required fields in the request body
  • Invalid field format (e.g., malformed email, invalid phone number)
  • Invalid enum values
  • Field value out of allowed range
Resolution: Review the errors array and correct each field according to the API specification.
HTTP Status: 400 Bad RequestDescription: The request could not be processed due to malformed syntax or invalid content.Example Response:
{
  "type": "invalid-request",
  "title": "Invalid Request",
  "status": 400,
  "detail": "Request body must be valid JSON.",
  "instance": "/customers",
  "request_id": "req_def456"
}
Common Causes:
  • Malformed JSON in request body
  • Invalid Content-Type header
  • Missing required headers
  • Request body too large
Resolution: Verify that your request body is valid JSON and includes all required headers.
HTTP Status: 400 Bad RequestDescription: One or more resource identifiers in the request are malformed or invalid.Example Response:
{
  "type": "invalid-identifier",
  "title": "Invalid Identifier",
  "status": 400,
  "detail": "The identifier 'invalid-id' is not a valid KSUID.",
  "instance": "/customers/invalid-id",
  "request_id": "req_ghi789"
}
Common Causes:
  • Invalid KSUID format in path or query parameters
  • Using an identifier from a different resource type
  • Malformed UUID or prefixed ID
Resolution: Ensure all identifiers are valid KSUIDs (27-character base62 strings) obtained from previous API responses.
HTTP Status: 400 Bad RequestDescription: The operation cannot be completed due to insufficient balance in the source account or wallet.Example Response:
{
  "type": "insufficient-balance",
  "title": "Insufficient Balance",
  "status": 400,
  "detail": "Wallet has insufficient USDC balance for this transaction.",
  "instance": "/transactions",
  "request_id": "req_jkl012"
}
Common Causes:
  • Attempting to transfer more than available balance
  • Balance reserved for pending transactions
  • Network fees not accounted for in available balance
Resolution: Check the account or wallet balance before initiating the transaction.
HTTP Status: 400 Bad RequestDescription: A configured resource limit has been reached for your organization.Example Response:
{
  "type": "limit-reached",
  "title": "Limit Reached",
  "status": 400,
  "detail": "Maximum number of API keys (10) has been reached.",
  "instance": "/api-keys",
  "request_id": "req_mno345"
}
Common Causes:
  • Maximum API keys created
  • Maximum webhook targets configured
  • Resource quota exceeded
Resolution: Delete unused resources or contact support to increase limits.
HTTP Status: 400 Bad RequestDescription: The authenticated user has access to multiple clients. You must specify which client to use.Example Response:
{
  "type": "multiple-clients",
  "title": "Multiple Clients",
  "status": 400,
  "detail": "Multiple clients are available; select an active client.",
  "instance": "/customers",
  "request_id": "req_pqr678"
}
Resolution: Include the appropriate client context in your request or select a default client in the dashboard.
HTTP Status: 401 UnauthorizedDescription: Authentication credentials are missing, invalid, or expired.Example Response:
{
  "type": "authentication-error",
  "title": "Authentication Required",
  "status": 401,
  "detail": "Missing or invalid authentication credentials.",
  "instance": "/customers",
  "request_id": "req_stu901"
}
Common Causes:
  • Missing x-api-key header
  • Invalid or revoked API key
  • Expired application token
  • Malformed authentication header
Resolution: Verify your API key is correct and active. Check that the x-api-key header is properly formatted.
HTTP Status: 403 ForbiddenDescription: Your credentials are valid but you do not have permission to perform this action.Example Response:
{
  "type": "forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "You do not have permission to access this customer.",
  "instance": "/customers/cst_xyz789",
  "request_id": "req_vwx234"
}
Common Causes:
  • Accessing a resource belonging to another organization
  • API key lacks required scopes
  • User role insufficient for the operation
  • Resource access restricted by policy
Resolution: Verify you have the necessary permissions. Contact your administrator to request access.
HTTP Status: 404 Not FoundDescription: The requested resource does not exist or has been deleted.Example Response:
{
  "type": "not-found",
  "title": "Customer Not Found",
  "status": 404,
  "detail": "Customer cst_2abc123 was not found.",
  "instance": "/customers/cst_2abc123",
  "request_id": "req_yza567"
}
Common Causes:
  • Resource was deleted
  • Incorrect resource ID
  • Resource belongs to a different organization
  • Typo in the resource path
Resolution: Verify the resource ID is correct. Use list endpoints to confirm the resource exists.
HTTP Status: 409 ConflictDescription: The request conflicts with the current state of the resource.Example Response:
{
  "type": "conflict",
  "title": "Customer Conflict",
  "status": 409,
  "detail": "A customer with external_id 'ext-123' already exists.",
  "instance": "/customers",
  "request_id": "req_bcd890"
}
Common Causes:
  • Duplicate external_id when creating a customer
  • Duplicate name for a unique resource
  • Attempting to transition to an invalid state
  • Concurrent modification conflict
Resolution: Use unique identifiers or fetch the existing resource to update it instead.
HTTP Status: 413 Payload Too LargeDescription: The request payload exceeds the maximum allowed size.Example Response:
{
  "type": "payload-too-large",
  "title": "Payload Too Large",
  "status": 413,
  "detail": "Request payload exceeds the maximum allowed size of 500 MB.",
  "instance": "/applications/app_123/documents",
  "request_id": "req_efg123"
}
Common Causes:
  • File upload exceeds 500 MB limit
  • Request body too large
  • Bulk operation with too many items
Resolution: Reduce the payload size or split into multiple requests.
HTTP Status: 422 Unprocessable EntityDescription: The request cannot be completed due to compliance restrictions.Example Response:
{
  "type": "compliance-blocked",
  "title": "Compliance Blocked",
  "status": 422,
  "detail": "This wallet address cannot be processed due to compliance restrictions.",
  "instance": "/transactions",
  "request_id": "req_hij456"
}
Common Causes:
  • Destination wallet address flagged by compliance screening
  • Transaction blocked by sanctions screening
  • Customer flagged for compliance review
  • Geographic restrictions
Resolution: Contact support for details on the compliance block. Do not attempt to circumvent compliance controls.
HTTP Status: 429 Too Many RequestsDescription: You have exceeded the rate limit for API requests.Example Response:
{
  "type": "rate-limited",
  "title": "Rate Limited",
  "status": 429,
  "detail": "Too many requests. Please retry later.",
  "instance": "/customers",
  "request_id": "req_klm789"
}
Rate Limit Headers:Every response includes rate limit information:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current one-minute window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the current window resets
Retry-AfterSeconds to wait before retrying (only on 429 responses)
Rate Limits by Authentication Type:
AuthenticationLimit
API Key60 requests per minute
JWT (Dashboard)600 requests per minute
Application Token100 requests per hour
Unauthenticated10 requests per minute
Resolution: Implement exponential backoff and respect the Retry-After header.

Server Errors (5xx)

HTTP Status: 500 Internal Server ErrorDescription: An unexpected error occurred on the server. The error details are sanitized for security.Example Response:
{
  "type": "internal-error",
  "title": "Internal Server Error",
  "status": 500,
  "detail": "An unexpected error occurred.",
  "instance": "/customers",
  "request_id": "req_nop012"
}
Resolution: Retry with exponential backoff. If the error persists, contact support with the request_id.
HTTP Status: 501 Not ImplementedDescription: The requested endpoint or feature is not yet implemented.Example Response:
{
  "type": "not-implemented",
  "title": "Not Implemented",
  "status": 501,
  "detail": "This endpoint is not implemented.",
  "instance": "/some-future-endpoint",
  "request_id": "req_qrs345"
}
Resolution: Check the API documentation for available endpoints. Contact support if you believe this is an error.
HTTP Status: 502 Bad GatewayDescription: An upstream provider returned an error.Example Response:
{
  "type": "provider-error",
  "title": "Provider Error",
  "status": 502,
  "detail": "An upstream provider returned an error.",
  "instance": "/transactions",
  "request_id": "req_tuv678"
}
Resolution: Retry with exponential backoff. These errors are typically transient.
HTTP Status: 503 Service UnavailableDescription: The service is temporarily unavailable, typically during maintenance.Example Response:
{
  "type": "service-unavailable",
  "title": "Service Unavailable",
  "status": 503,
  "detail": "Service is temporarily unavailable.",
  "instance": "/customers",
  "request_id": "req_wxy901"
}
Resolution: Retry with exponential backoff. Check our status page for maintenance announcements.

Error Handling Best Practices

Basic Error Handler

const response = await fetch('https://api.platform.dakota.xyz/customers', {
  headers: { 'x-api-key': apiKey }
});

if (!response.ok) {
  const problem = await response.json();

  // Log the request_id for support tickets
  console.error(`Error [${problem.request_id}]: ${problem.title}`);

  switch (problem.status) {
    case 400:
      // Handle validation errors
      if (problem.errors) {
        problem.errors.forEach(err => {
          console.log(`Field '${err.field}': ${err.message}`);
        });
      }
      break;
    case 401:
      console.log('Check your API key');
      break;
    case 404:
      console.log('Resource not found');
      break;
    case 429:
      const retryAfter = response.headers.get('Retry-After') || 60;
      console.log(`Rate limited. Retry after ${retryAfter} seconds`);
      break;
    default:
      console.error(`Error: ${problem.detail}`);
  }
}

Retry Logic with Exponential Backoff

For transient errors (5xx, rate limits), implement exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
  const retryableStatuses = [429, 500, 502, 503];

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      if (response.ok) {
        return response.json();
      }

      const problem = await response.json();

      // Check if error is retryable
      if (retryableStatuses.includes(problem.status) && attempt < maxRetries) {
        let delay;

        if (problem.status === 429) {
          // Use Retry-After header if available
          delay = (parseInt(response.headers.get('Retry-After')) || 60) * 1000;
        } else {
          // Exponential backoff: 1s, 2s, 4s
          delay = Math.pow(2, attempt) * 1000;
        }

        console.log(`Retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
        await new Promise(r => setTimeout(r, delay));
        continue;
      }

      // Non-retryable error
      throw new Error(`API Error [${problem.request_id}]: ${problem.title} - ${problem.detail}`);

    } catch (networkError) {
      // Network errors are retryable
      if (attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Network error, retrying in ${delay}ms`);
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      throw networkError;
    }
  }
}

// Usage
try {
  const customer = await fetchWithRetry(
    'https://api.platform.dakota.xyz/customers/cst_123',
    { headers: { 'x-api-key': apiKey } }
  );
  console.log('Customer:', customer);
} catch (error) {
  console.error('Request failed after retries:', error.message);
}

Idempotency for Safe Retries

For POST requests, always include the x-idempotency-key header to safely retry failed requests:
curl -X POST https://api.platform.dakota.xyz/customers \
  -H "x-api-key: YOUR_API_KEY" \
  -H "x-idempotency-key: unique-request-id-123" \
  -H "Content-Type: application/json" \
  -d '{"customer_type": "business", "name": "Acme Corp"}'
Important: The idempotency key must be unique per logical operation. Reusing a key with different request parameters may return the cached response from the original request.

Troubleshooting

Getting Help

When contacting support about an error:
  1. Always include the request_id from the error response
  2. Provide the full error response body
  3. Include the request method, path, and relevant headers (redact the API key)
  4. Describe what you expected vs. what happened

Common Issues

Symptoms: All requests return authentication errors.Checklist:
  1. Verify the x-api-key header is included (not X-Api-Key or api-key)
  2. Check that the API key is not expired or revoked
  3. Ensure there are no extra spaces or newlines in the key
  4. Verify you’re using the correct environment (sandbox vs production)
Symptoms: Getting validation errors without clear field information.Checklist:
  1. Check the errors array in the response for field-level details
  2. Verify your Content-Type header is application/json
  3. Ensure the request body is valid JSON
  4. Compare your request against the OpenAPI specification
Symptoms: Hitting rate limits during normal operation.Checklist:
  1. Check X-RateLimit-Remaining header to monitor usage
  2. Implement request batching where possible
  3. Add caching for frequently accessed resources
  4. Consider using webhooks instead of polling
For detailed troubleshooting, see our Troubleshooting Guide.