API Reference
The Indexly REST API gives Pro, Agency, and Enterprise users programmatic access to sites, crawls, and sitemaps.
Authentication
All API requests must include a Bearer token in the Authorization header.
Generate tokens from Settings → API Tokens.
Authorization: Bearer <your-api-token>
Plan requirement
API access is available on Pro, Agency, and Enterprise plans only. Requests from Free or Starter accounts receive a 403 response.
Base URL
https://indexly.dev/api
All responses are JSON. Paginated list endpoints follow Laravel's standard pagination envelope with data, links, and meta keys.
Endpoints
/api/sites
Return a paginated list of all sites belonging to the authenticated user.
Example request
curl https://indexly.dev/api/sites \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": 1,
"name": "My Website",
"url": "https://example.com",
"crawl_frequency": "weekly",
"is_active": true,
"last_crawled_at": "2026-04-10T14:23:00+00:00",
"next_crawl_at": "2026-04-17T14:23:00+00:00",
"created_at": "2026-04-01T09:00:00+00:00",
"latest_crawl": { "id": 42, "status": "completed", ... },
"sitemap_url": "https://cdn.indexly.dev/sitemaps/1/1/42/sitemap.xml"
}
],
"links": { ... },
"meta": { "current_page": 1, "total": 1, ... }
}
/api/sites
Create a new site. Subject to your plan's site limit.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | Yes | Max 100 characters |
| url | string | Yes | Must be a valid http/https URL. Private IPs are rejected. |
| crawl_frequency | string | Yes |
manual,
weekly, or
daily
|
Example request
curl -X POST https://indexly.dev/api/sites \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"name":"My Blog","url":"https://myblog.com","crawl_frequency":"weekly"}'
Example response 201 Created
{
"data": {
"id": 2,
"name": "My Blog",
"url": "https://myblog.com",
"crawl_frequency": "weekly",
"is_active": true,
"last_crawled_at": null,
"next_crawl_at": null,
"created_at": "2026-04-12T10:00:00+00:00",
"latest_crawl": null,
"sitemap_url": null
}
}
/api/sites/{site}
Return a single site by ID, including the latest crawl and sitemap URL.
Example request
curl https://indexly.dev/api/sites/1 \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Same shape as a single item in the list response. Returns 404 if not found or not owned by the authenticated user.
/api/sites/{site}
Soft-delete a site. Crawl history and sitemaps are retained.
Example request
curl -X DELETE https://indexly.dev/api/sites/2 \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Returns 204 No Content on success.
/api/sites/{site}/crawl
Trigger a new crawl for the given site. The crawl is queued asynchronously. Rate-limited to 10 requests per minute.
Returns 409 Conflict if a crawl is already queued or running for this site.
Example request
curl -X POST https://indexly.dev/api/sites/1/crawl \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Example response 202 Accepted
{
"data": {
"id": 43,
"site_id": 1,
"status": "queued",
"pages_found": null,
"pages_in_sitemap": null,
"started_at": null,
"completed_at": null,
"sitemap_url": null,
"created_at": "2026-04-12T10:05:00+00:00"
}
}
/api/sites/{site}/crawls
Return a paginated crawl history for the given site (20 per page, newest first).
Example request
curl https://indexly.dev/api/sites/1/crawls \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Example response 200 OK
{
"data": [
{
"id": 42,
"site_id": 1,
"status": "completed",
"pages_found": 312,
"pages_in_sitemap": 310,
"started_at": "2026-04-10T14:20:00+00:00",
"completed_at": "2026-04-10T14:23:00+00:00",
"sitemap_url": "https://cdn.indexly.dev/sitemaps/1/1/42/sitemap.xml",
"created_at": "2026-04-10T14:20:00+00:00"
}
],
"links": { ... },
"meta": { "current_page": 1, "total": 5, ... }
}
/api/crawls/{crawl}
Return a single crawl by ID. Includes error_message only when status is failed.
Example request
curl https://indexly.dev/api/crawls/42 \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json"
Crawl status values
| Value | Meaning |
|---|---|
| queued | Waiting in the queue |
| running | Actively crawling |
| completed | Finished successfully — sitemap available |
| failed | Crawl failed — check error_message |
/api/crawls/{crawl}/sitemap
Redirects (302) to the public sitemap XML URL on Cloudflare R2.
Returns 404 if no sitemap is available for this crawl.
Example request
curl -L https://indexly.dev/api/crawls/42/sitemap \
-H "Authorization: Bearer <token>" \
-H "Accept: application/xml"
Use -L with curl to follow the redirect and land on the raw XML file.
Rate Limiting
Rate limit headers are returned on every response. When a limit is exceeded, the API responds with 429 Too Many Requests.
| Endpoint group | Limit | Keyed by |
|---|---|---|
| All API endpoints | 60 requests / minute | User ID |
| POST /sites/{site}/crawl | 10 requests / minute | User ID |
Error Responses
All error responses follow a consistent shape with a human-readable message field and an optional errors object on validation failures.
| Status | Meaning |
|---|---|
| 401 | Missing or invalid Bearer token |
| 402 | Insufficient crawl credits |
| 403 | Plan does not include API access, or resource belongs to another user |
| 404 | Resource not found |
| 409 | Crawl already queued or running for this site |
| 422 | Validation error (field details in errors key) or SSRF-blocked URL |
| 429 | Rate limit exceeded |
Error body shape
{
"message": "Human-readable description of the error.",
"errors": {
"url": ["The url field is required."]
}
}