Authentication
Every request needs your API key in theX-API-Key header. The Python
SDK reads it from the PROFOUND_API_KEY env var.
Rate limit
600 requests per hour, per key. Anything above returns429 Too Many Requests. Cache responses where you can and batch period-over-period or
multi-asset queries instead of fanning out.
end_date is exclusive — add one day
end_date is parsed at the start of that day in Eastern Time,
so it’s excluded from the response. To include all of May 10, send
end_date="2026-05-11".
| Window you want to display | What to send |
|---|---|
May 4 → May 10 (7 days, inclusive) | start_date="2026-05-04", end_date="2026-05-11" |
April 1 → April 30 (full month) | start_date="2026-04-01", end_date="2026-05-01" |
date_interval buckets ("day" / "week" / "month") are also
computed in ET.
Read column positions from info.query, not your request
Each row in the response packs its metrics and dimensions as arrays.
The order of values in those arrays comes from info.query.metrics and
info.query.dimensions — not from the order you sent in the
request. Always look it up:
Period-over-period deltas are client-side
The API doesn’t return change vs the previous period. Run the same call twice — current window and a prior window of equal length — and subtract.Don’t average daily rows to get a period score
A call withdimensions=["date"] returns one row per day. A call without
date returns one row for the whole window. These are different
numbers: the period score is traffic-weighted, an average of daily
rows is not. Use the no-date call for headlines; use the with-date
call for charts. Never derive one from the other.
Pagination
Defaultpagination.limit is 100. Max is 50,000. Use
info.total_rows (returned on every response) to decide whether to
paginate. Almost all queries fit in a single 50k page; only heavy
dimensions=["url", ...] citation queries usually need a second page.
offset by limit until you’ve covered
total_rows.
Filters
Every report endpoint accepts afilters array of {field, operator, value} objects:
| Operator | What it does |
|---|---|
is | Exact match (scalar value) |
not_is | Not equal |
in | Match any value in an array |
not_in | Match none of the values in an array |
contains | Substring match (case-sensitive) |
contains_case_insensitive | Substring match (case-insensitive) |
matches | Regex match |
prompt_type (with values like "visibility") maps to the app’s view
toggles. Send prompt_type=visibility on Citations / Visibility queries
to mirror the default UI scope.
Error responses
| Status | Meaning | What to check |
|---|---|---|
400 | Validation error | The response body’s detail / errors field. |
401 | API key missing or invalid | The X-API-Key header; whether the key has been revoked. |
403 | Key valid but no access | The category_id may belong to a different org. |
404 | Wrong path | Typo or wrong API version. |
429 | Rate limited | Back off; throttle to ≤600/hr. |
5xx | Server error | Retry with exponential backoff. |