Error Handling

How to handle errors and manage credits with the Addresspenny API.

Error responses

When a request fails, the API returns a JSON error object with a code and human-readable message. Always check the HTTP status code first, then parse the error body for details.

{
  "error": {
    "code": "error_code",
    "message": "A description of what went wrong"
  }
}

Credit management

Each address validation consumes one credit. When credits are exhausted, the API returns 402 Payment Required with your current balance:

{
  "error": {
    "code": "insufficient_credits",
    "message": "No address credits remaining",
    "credits_remaining": 0,
    "credits_limit": 50
  }
}

The credits_remaining and credits_limit fields let you track usage programmatically — for example, to alert your team before credits run out or to pause processing until more are purchased.

Invalid input (422)

Returned when the request body is missing or invalid:

{
  "error": {
    "code": "validation_failed",
    "message": "Original input can't be blank"
  }
}

Unauthorized (401)

Returned when the Authorization header is missing or the token is invalid. Double-check that your token is correct and hasn't been revoked.

Not found (404)

Returned when the account ID or address ID doesn't exist, or when you don't have access to the specified account.

Rate limiting

API requests are rate limited per token to ensure fair usage. Write endpoints (create, batch) allow 60 requests per minute. Read endpoints (index, show) allow 120 requests per minute.

When rate limited, the API returns 429 Too Many Requests with a retry_after value in seconds. Your integration should back off and retry after the indicated period.

Batch validation

To validate multiple addresses in a single request, use the batch endpoint:

curl -X POST https://addresspenny.com/api/v1/accounts/acct_1a2b3c/addresses/batch \
  -H "Authorization: Bearer your_api_token" \
  -H "Content-Type: application/json" \
  -d '{"addresses": ["123 Main St, Springfield, IL", "350 Fifth Ave, New York, NY"]}'

Each address in the batch consumes one credit. The batch endpoint checks that you have enough credits for all addresses before processing any of them. Maximum batch size is 100.

Permission scopes

API tokens can be created with specific permission scopes to limit what they can do. If a token lacks the required scope for a request, the API returns 403 Forbidden with details about the required and granted scopes. See the API Reference for the full list of scopes.

Idempotent requests

When building integrations that may retry on failure, include an Idempotency-Key header with your POST requests. If the same key and request body are sent again, the API returns the original response without creating duplicates.

curl -X POST https://addresspenny.com/api/v1/accounts/acct_1a2b3c/addresses \
  -H "Authorization: Bearer your_api_token" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-unique-key-abc123" \
  -d '{"address": {"original_input": "123 Main St, Springfield, IL"}}'

Keys expire after 24 hours. If you reuse a key with a different request body, the API returns 409 Conflict. Use a UUID or similar unique value for each distinct operation.

Working with multiple accounts

If you belong to multiple accounts (personal and team), each has its own credit balance and address history. List your accounts to find the right one:

curl -H "Authorization: Bearer your_api_token" \
  https://addresspenny.com/api/v1/accounts

Use your team account for shared work, or your personal account for individual use. The account ID in the URL determines which credit balance is charged.