1. Developers
  2. Getting started

Pagination and errors

Handle cursor-based pagination and interpret standard error responses.

Updated October 5, 2026

The HowdyBell API uses cursor-based pagination for list endpoints. This approach is efficient for large datasets and avoids the issues associated with offset-based pagination.

Cursor-Based Pagination

List endpoints such as List contacts and List conversations return a next_cursor field. Use this cursor to fetch the next page of results.

Response Structure

{
  "data": [
    { "id": 1, "first_name": "Jane" },
    { "id": 2, "first_name": "John" }
  ],
  "next_cursor": "eyJwYWdlIjoyfQ",
  "total": 150
}
  • data: An array of objects for the current page.
  • next_cursor: A string token for the next page. If null, there are no more results.
  • total: The total number of matching records.

Fetching the Next Page

Pass the next_cursor value as the cursor query parameter.

curl -X GET "https://howdybell.com/api/v1/contacts?location_id=101&cursor=eyJwYWdlIjoyfQ" \
  -H "Authorization: Bearer hb_live_your_key_here"

Pagination Limits

  • The default page size is 200 items.
  • You cannot change the page size via query parameters.
  • Cursors are opaque strings. Do not attempt to decode or modify them.

Error Responses

All errors return a JSON body with a consistent structure. The HTTP status code indicates the type of error.

401 Unauthorized

Returned when authentication fails.

{
  "error": "invalid_api_key"
}

404 Not Found

Returned when a resource does not exist or is not accessible.

{
  "error": "contact.not_found"
}

Common 404 errors include:

  • location.not_found: Invalid or out-of-workspace location ID.
  • contact.not_found: Contact ID does not exist in the specified location.
  • tag.not_found: Tag ID does not exist in the workspace.

422 Unprocessable Entity

Returned when request validation fails.

{
  "message": "The first name field is required.",
  "errors": {
    "first_name": [
      "The first name field is required."
    ]
  }
}

429 Too Many Requests

Returned when you exceed the rate limit.

{
  "message": "Too Many Attempts."
}

The response carries a Retry-After header with the number of seconds to wait.

Error Handling Best Practices

  1. Check Status Codes: Always inspect the HTTP status code before parsing the body.
  2. Log Error Bodies: Include the full JSON body in your logs for debugging.
  3. Retry on 429: Wait the number of seconds in the Retry-After header, then try again.
  4. Handle 404s Gracefully: Do not treat 404 errors as fatal if the resource may have been deleted.
  5. Validate Inputs: Check required fields before sending requests to avoid 422 errors.

Example: Robust Pagination Loop

async function fetchAllContacts(locationId, apiKey) {
  let cursor = null;
  let allContacts = [];

  do {
    let url = `https://howdybell.com/api/v1/contacts?location_id=${locationId}`;
    if (cursor) {
      url += `&cursor=${encodeURIComponent(cursor)}`;
    }

    const response = await fetch(url, {
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Accept': 'application/json'
      }
    });

    if (!response.ok) {
      throw new Error(`API error: ${response.status}`);
    }

    const data = await response.json();
    allContacts = allContacts.concat(data.data);
    cursor = data.next_cursor;
  } while (cursor);

  return allContacts;
}

Note: The total field is provided for informational purposes. Do not rely on it to determine when to stop paginating. Always check next_cursor.

Pagination and errors | HowdyBell Developers