Heading API reference
Complete reference for the Heading REST API
Programmatic access to properties, prompts, visibility, AI responses, competitors, sources, and tasks. Authenticate with API keys. Get JSON responses.
Base URL
https://api.useheading.com/v1Authentication
All requests require an API key passed as a Bearer token in the Authorization header.
Create API keys from Settings > API in the Heading dashboard. Keys use the hdg_sk_live_ prefix.
curl https://api.useheading.com/v1/properties \
-H "Authorization: Bearer hdg_sk_live_abc123..."API keys are shown once at creation and cannot be retrieved later. Store them securely.
Access levels
The API is currently read-only: every endpoint is GET. Both key access levels are accepted:
| Level | Permissions |
|---|---|
| Read | GET requests |
| Write | GET requests. Reserved for upcoming write endpoints. Grants nothing extra today. |
Data access
The API returns data for properties on a paid plan (Starter, Growth, or Scale). Free properties do not appear in any endpoint, including /v1/properties.
Property scoping
Keys can be scoped to specific properties or granted access to all properties on the team. Scoped keys only return data for their allowed properties. Filtering by a propertyId outside the key's scope returns an empty list, not an error.
Resources
Pagination
List endpoints accept limit and offset:
limit: integer. Maximum results per page. Default: 100, max: 1000.offset: integer. Rows to skip. Default: 0.
total in the response is the full match count, independent of pagination.
Date ranges
Time-series endpoints (/v1/visibility, /v1/responses, /v1/sources, /v1/sources/urls) accept from and to as UTC calendar days (yyyy-MM-dd). Both bounds are inclusive. Default range: the last 30 UTC days. All dates in responses are UTC.
Response format
All responses return JSON with a consistent structure.
Success: list
{
"data": [...],
"total": 5
}Success: detail
{
"data": { ... }
}Error
{
"error": {
"code": "MISSING_AUTH",
"message": "Authorization header is required"
}
}Every error, including 429, uses this envelope.
Status codes
| Status | Meaning |
|---|---|
200 | Success |
400 | Invalid request: malformed query parameter |
401 | Unauthorized: invalid or missing API key |
403 | Forbidden: insufficient permissions |
404 | Not found: no such resource in the key's scope |
429 | Rate limited: too many requests |
500 | Internal server error |
Error codes
| Code | Status | When |
|---|---|---|
MISSING_AUTH | 401 | No Authorization header |
INVALID_AUTH | 401 | Header is not Bearer {key} |
INVALID_KEY | 401 | Malformed, unknown, or revoked API key |
FORBIDDEN | 403 | Read-only key attempting a write operation |
INVALID_PARAM | 400 | Query parameter failed validation |
NOT_FOUND | 404 | Detail id does not exist in the key's scope |
RATE_LIMIT_EXCEEDED | 429 | Rate limit exceeded |
INTERNAL_ERROR | 500 | Server error |
Rate limits
- 100 requests/min per API key
X-RateLimit-Limit,X-RateLimit-Remaining, andX-RateLimit-Resetheaders are included on all responses- Rate-limited responses include a
Retry-Afterheader (seconds until reset) and the standard error envelope with codeRATE_LIMIT_EXCEEDED