Skip to main content

Error Response Format

All Kintsugi API errors follow a consistent JSON format:
{
  "detail": "Error message describing what went wrong"
}
For validation errors (422), the response includes detailed field-level information:
{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "external_id"],
      "msg": "Field required",
      "input": null
    }
  ]
}

HTTP Status Codes

Status CodeError TypeDescriptionCommon Causes
400Bad RequestInvalid request data or parametersMissing required fields, invalid data types, business logic violations
401UnauthorizedInvalid or missing authenticationMissing API key, invalid API key, expired token
403ForbiddenInsufficient permissionsUser lacks access to organization, admin-only endpoint
404Not FoundResource does not existInvalid ID, deleted resource, wrong organization
409ConflictResource conflictDuplicate creation, state conflicts, concurrent modifications
422Unprocessable EntityValidation errorsInvalid field values, constraint violations, business rules
429Too Many RequestsRate limit exceededExceeding 10,000 requests per minute limit
Status CodeError TypeDescriptionCommon Causes
500Internal Server ErrorUnexpected server errorDatabase errors, unhandled exceptions, system failures
503Service UnavailableExternal service unavailableThird-party API failures, maintenance windows

Common Error Messages

Authentication Errors

  • Error Response
  • Solution
{
  "detail": "API key is missing or empty."
}
  • Error Response
  • Solution
{
  "detail": "Unauthenticated request."
}
  • Error Response
  • Solution
{
  "detail": "User does not have access to the specified organization"
}
  • Error Response
  • Solution
{
  "detail": "Admin access required for this endpoint."
}

Validation Errors

{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "external_id"],
      "msg": "Field required",
      "input": null
    }
  ]
}
Solution: Include all required fields in your request
{
  "detail": [
    {
      "type": "enum",
      "loc": ["body", "currency"],
      "msg": "Input should be 'USD', 'CAD', 'EUR'...",
      "input": "INVALID",
      "ctx": {"expected": "one of USD, CAD, EUR..."}
    }
  ]
}
Solution: Use valid enum values as specified in the API documentation
{
  "detail": [
    {
      "type": "value_error",
      "loc": ["body", "discount_amount"],
      "msg": "'discount_amount' must be less than the 'amount'.",
      "input": 100.00,
      "ctx": {"error": "discount exceeds amount"}
    }
  ]
}
Solution: Ensure your data follows business rules and constraints

Error Handling Best Practices

1

Implement Proper HTTP Status Code Handling

Check the response status code and handle each type appropriately:
import requests

try:
    response = requests.get(url, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    if e.response.status_code == 401:
        # Handle authentication error
        print("Invalid API key")
    elif e.response.status_code == 429:
        # Handle rate limiting
        retry_after = e.response.headers.get('Retry-After', 60)
        print(f"Rate limited. Retry after {retry_after} seconds")
    elif e.response.status_code == 422:
        # Handle validation errors
        errors = e.response.json()['detail']
        for error in errors:
            print(f"Validation error: {error['msg']}")
2

Implement Exponential Backoff

For rate limiting and temporary errors, implement exponential backoff:
import time
import random

def make_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            return response
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 429:
                # Exponential backoff with jitter
                wait_time = (2 ** attempt) + random.uniform(0, 1)
                time.sleep(wait_time)
                continue
            else:
                raise
    raise Exception("Max retries exceeded")
3

Log Errors Appropriately

Log errors with sufficient context for debugging:
import logging

logger = logging.getLogger(__name__)

try:
    response = requests.get(url, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    logger.error(
        "API request failed",
        extra={
            "status_code": e.response.status_code,
            "url": url,
            "response_body": e.response.text,
            "organization_id": headers.get("x-organization-id")
        }
    )
    raise
4

Provide User-Friendly Error Messages

Transform technical errors into user-friendly messages:
def handle_api_error(error):
    if error.response.status_code == 401:
        return "Please check your API key and try again."
    elif error.response.status_code == 404:
        return "The requested resource was not found."
    elif error.response.status_code == 422:
        return "Please check your input data and try again."
    elif error.response.status_code == 429:
        return "Too many requests. Please wait a moment and try again."
    else:
        return "An unexpected error occurred. Please try again later."

Troubleshooting Common Issues

  • Missing API Key
  • Invalid API Key
Error: API key is missing or empty.Solution: Ensure you’re including both the x-api-key and x-organization-id headers in your requests:
curl -H "x-api-key: your-api-key" \
     -H "x-organization-id: your-org-id" \
     https://api.trykintsugi.com/v1/tax/estimate
Kintsugi uses API key authentication via headers (not bearer token). Both headers are required.
  • Missing Required Fields
  • Invalid Data Types
Error: Field requiredSolution: Check the API documentation for required fields and ensure all are included in your request body.
  • Resource Not Found
  • Access Denied
Error: Resource not foundSolution:
  1. Verify the resource ID is correct
  2. Check if the resource belongs to your organization
  3. Ensure the resource hasn’t been deleted