Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.propal.io/llms.txt

Use this file to discover all available pages before exploring further.

All list endpoints use cursor-based pagination. This is more reliable than offset-based pagination: insertions and deletions don’t cause skipped or duplicated records.

Request parameters

ParameterTypeDefaultDescription
limitinteger25Number of items to return. Min: 1, max: 100.
afterstringCursor from a previous response. Fetch the next page starting after this cursor.

Response format

Every list endpoint returns the same pagination structure:
{
  "data": [
    { "id": "abc-123", "name": "Item 1" },
    { "id": "def-456", "name": "Item 2" }
  ],
  "pagination": {
    "has_more": true,
    "next_cursor": "ZGVmLTQ1Ng",
    "total_count": 142
  }
}
FieldTypeDescription
has_morebooleantrue if there are more items after this page.
next_cursorstring | nullOpaque cursor to pass as the after parameter for the next page. null when on the last page.
total_countintegerTotal number of items matching your query (across all pages).

Paginating through all results

async function fetchAllLeads(apiKey) {
  const leads = [];
  let cursor = undefined;

  while (true) {
    const url = new URL('https://api.propal.io/v1/leads');
    url.searchParams.set('limit', '100');
    if (cursor) url.searchParams.set('after', cursor);

    const response = await fetch(url, {
      headers: { 'Authorization': `Bearer ${apiKey}` },
    });
    const { data, pagination } = await response.json();

    leads.push(...data);

    if (!pagination.has_more) break;
    cursor = pagination.next_cursor;
  }

  return leads;
}

Filtering and sorting

List endpoints support filters via query parameters. Filters are combined with pagination:
# List only sent proposals, 50 per page
curl "https://api.propal.io/v1/proposals?status=approved&limit=50" \
  -H "Authorization: Bearer pp_live_YOUR_KEY"

# Search leads by name
curl "https://api.propal.io/v1/leads?search=acme&limit=10" \
  -H "Authorization: Bearer pp_live_YOUR_KEY"
Available filters vary per endpoint — check the specific resource documentation for details.
Cursors are opaque strings. Don’t try to decode, modify, or construct them manually. Always use the next_cursor value returned by the API.

Best practices

  • Use the largest limit you need. Fewer requests = fewer rate limit tokens consumed. Use limit=100 for bulk operations.
  • Stop when has_more is false. Don’t make an extra request — the API tells you when you’ve reached the end.
  • Use total_count for progress. Display progress bars or “showing X of Y” indicators using total_count.