Developers
Developer API
Programmatic access to your XenonFlare workspace for integrations, CI pipelines, and internal tools.
Quickstart
Three lines to your first API call
Authenticate with a Bearer key from Developer API in the app sidebar (Starter or Growth). 1000 reads/hr and 60 writes/hr per key · 500 org writes/day · up to 5 active keys.
curl -H "Authorization: Bearer xf_live_xxxxxxxx" \
https://api.xenonflare.com/api/v1/propertiesBase URL: https://api.xenonflare.com/api/v1 · Rate limits · All endpoints · SEO automation API
Most integrations queue a scan, poll GET /jobs/:id until status is completed, then read results or shared report links.
Overview
The Developer API is organization-scoped. Each API key belongs to one workspace and carries explicit permission scopes. All authenticated routes return JSON with a consistent envelope and include a requestId in meta for support.
- Read endpoints list properties, jobs, organization details, and usage.
- Write endpoints create properties and queue SEO scans or crawls.
- Keys use the format
xf_live_...(live) orxf_test_...(sandbox) and can be revoked instantly from the app.
Authentication
Send your API key as a Bearer token in the Authorization header. Create keys in the web app — they are shown once at creation; store them securely.
curl -H "Authorization: Bearer xf_live_xxxxxxxx" \
https://api.xenonflare.com/api/v1/propertiesRevoked or invalid keys receive 401 with error.code: "api_key_invalid".
Test keys (sandbox)
Choose Test when creating a key to get an xf_test_… sandbox credential. Test keys read real workspace data but write endpoints return mock responses with no side effects — ideal for CI pipelines and integrator onboarding. Writes include the X-Developer-Api-Mode: test response header.
Agencies and portfolio monitoring
Agencies on Growth run one workspace with many client properties, then automate nightly POST /scans/batch, webhook alerts, and CSV activity exports for client reporting. Scoped keys let you separate read-only dashboards from automation that queues crawls. See the agency portfolio guide and SEO automation API landing for positioning and integration patterns.
Request ID
Send an optional X-Request-Id header on any authenticated request. When provided, the same value is echoed in meta.requestId on success and error responses — useful when contacting support or correlating logs on your side.
curl -H "Authorization: Bearer xf_live_xxxxxxxx" \
-H "X-Request-Id: deploy-2026-06-07-001" \
https://api.xenonflare.com/api/v1/organizationScopes
When creating a key, select only the scopes your integration needs.
| Scope | Access |
|---|---|
org:read | Organization overview |
properties:read | List and read website properties |
properties:write | Create new properties |
jobs:read | List and read scan/crawl jobs |
jobs:write | Queue scans and crawls |
usage:read | Usage totals and plan limits |
reports:read | List and read shared audit reports |
gsc:read | Read cached Google Search Console snapshots (GET /properties/:id/gsc, GET /organization/gsc). Connect GSC in the web app first. Field reference. |
gsc:write | Trigger GSC snapshot refresh (POST /properties/:id/gsc/sync) |
webhooks:read | List outbound webhook endpoints |
webhooks:write | Create, update, and delete webhook endpoints |
See also the nightly crawl guide, CI pipeline guide, and agency portfolio guide for automation patterns.
Endpoints
System
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | None | API reachability — returns status, version, timestamp, and a statusPage URL (status.xenonflare.com) |
Organization
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /organization | org:read | Workspace summary and usage totals |
Properties
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /properties | properties:read | Paginated list of website properties |
| POST | /properties | properties:write | Create property — body: { "url", "name?" } |
| GET | /properties/:id | properties:read | Single property detail — optional ?include=gsc,lastScan |
| GET | /properties/:id/issues | properties:read | Paginated SEO issues with lifecycle summary |
| POST | /properties/:id/scans | jobs:write | Queue an SEO scan job (seo-scan) |
| POST | /properties/:id/crawls | jobs:write | Queue a crawl (same job type as scans) |
Optional scan/crawl body: { "maxPages": number, "maxDepth": number }. Successful queue responses return 202 Accepted. Use ?include=gsc,lastScan on property list/detail to embed GSC summary or last scan metadata without extra round trips.
Monitoring, webhooks, reports & Search Console
Monitoring & status pages
Uptime and SSL monitoring is available on Starter+ workspaces. Probes run about every 5 minutes for verified properties with monitoring enabled. Customer status pages are published at https://xenonflare.com/status/{slug}— not to be confused with XenonFlare's own platform status at status.xenonflare.com.
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /uptime | monitoring:read or properties:read | Workspace uptime overview — all properties with latest probe and SSL state |
| GET | /properties/:id/uptime/history | monitoring:read or properties:read | Probe history for charts (retention depends on plan — 7 / 30 / 90 days) |
| PATCH | /properties/:id/uptime | properties:write or status-pages:write | Enable or pause monitoring; set probe method (auto, HEAD, GET) and optional HTTP basic auth for protected sites |
| GET | /properties/:id/status-page | properties:read | Public status page settings (slug, components, publish state) |
| PUT | /properties/:id/status-page | status-pages:write or properties:write | Publish or update a customer status page — returns public URL when enabled |
| DELETE | /properties/:id/status-page | status-pages:write or properties:write | Unpublish and remove status page settings |
Per-property probe settings apply to the homepage and every enabled status-page component URL on the same schedule. Use auto (HEAD then GET), force GET for strict endpoints, or add basic auth for staging. Pair with monitoring webhooks (uptime.down, uptime.recovered, ssl.expiring, ssl.invalid) for paging or chat alerts. Plan caps for monitoring and status pages are on GET /limits under data.uptime. Product overview: uptime & status pages.
Public status endpoints (no API key)
Customer status pages are served from the marketing app. These routes live on https://api.xenonflare.com/api and are also proxied for public pages:
| Method | Path | Description |
|---|---|---|
| GET | /public/status/{slug} | JSON snapshot — optional ?windowHours= (plan-clamped) |
| GET | /public/status/by-host?host= | JSON snapshot for Agency custom domains (CNAME → status-pages.xenonflare.com) |
| GET | /public/status/{slug}/feed.xml | RSS feed — incidents and scheduled maintenance |
| GET | /public/status/{slug}/feed.atom | Atom feed — same content as RSS |
| GET | /public/status/by-host/feed.xml?host= | RSS for custom domain hosts |
Custom status domain (Agency)
Agency workspaces can publish on status.client.com. Save customDomain via PUT /properties/:id/status-page, then verify DNS in the web app (POST /portal/.../status-page/verify-domain — session auth, not Developer API). Response fields include customDomainVerified, customDomainPublicUrl, and statusPageCnameTarget (status-pages.xenonflare.com).
Maintenance windows (Growth+)
Scheduled maintenance windows suppress down alerts and auto incidents during the window, and appear on the public status page. Manage them in the web app under property → Public status page (GET/POST/DELETE /portal/.../maintenance-windows). Requires Growth plan or higher.
Jobs
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /jobs | jobs:read | Paginated list of jobs |
| GET | /jobs/:id | jobs:read | Job status, stable result payload, and recent logs |
| POST | /jobs/:id/cancel | jobs:write | Cancel a pending or processing job. Website scans with saved crawl progress return resumeCrawlAvailable and a resume hint in message. |
| POST | /scans/batch | jobs:write | Queue up to 25 scans — per-property success/error in results |
Job response examples
POST /jobs/:id/cancel may return resumeCrawlAvailable when a website scan stops mid-crawl. Completed scans expose a stable result object on GET /jobs/:id.
{
"job": {
"id": "507f1f77bcf86cd799439014",
"type": "seo-scan",
"status": "cancelled",
"progress": 42,
"propertyId": "507f1f77bcf86cd799439012"
},
"message": "Crawl progress was saved. You can resume this scan from the dashboard.",
"resumeCrawlAvailable": true
}Optional filters on GET /jobs: status (pending, processing, completed, failed, cancelled), propertyId, and type (for example seo-scan).
Phased website scans. Site scans queue a root seo-scan job — poll that id for progress and results. Runner workers execute internal phases (website-crawl, website-audit, website-scan-persist) that are not returned by the Developer API. Single-page scans use root website-page-scan with website-page-* phases from the portal UI only (not Developer API v1).
Product workspaces
Growth-oriented capabilities expose read endpoints on properties:read and async jobs on jobs:write. Poll GET /jobs/:id after queueing cluster builds, decay scans, link sync, GEO drift checks, brand mention probes, or competitor snapshots. Plan gates return 403 plan_required when the workspace tier does not include the capability.
Content & backlinks
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /organization/product-capabilities | org:read | Plan-gated capability registry |
| GET | /properties/:id/content/workspace | properties:read | Clusters, decay snapshots, internal link suggestions |
| POST | /properties/:id/content/jobs/keyword-cluster-build | jobs:write | Queue GSC keyword clustering (Starter+) |
| POST | /properties/:id/content/jobs/content-decay-scan | jobs:write | Queue 28-day GSC decay scan (Growth+) |
| GET | /properties/:id/backlinks/workspace | properties:read | Internal link graph snapshots |
| POST | /properties/:id/backlinks/jobs/gsc-links-sync | jobs:write | Queue crawl link graph snapshot (Starter+: plan limits apply) |
curl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/properties/PROPERTY_ID/content/workspacecurl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/properties/PROPERTY_ID/backlinks/workspaceGEO monitoring
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /properties/:id/geo/settings | properties:read | Brand mention schedule, drift summary, usage |
| PATCH | /properties/:id/geo/settings | properties:write | Update scheduled brand mention probes (Growth+) |
| POST | /properties/:id/geo/jobs/geo-drift-check | jobs:write | Compare llms.txt / AI robots vs prior crawl (Starter+) |
| POST | /properties/:id/geo/jobs/brand-mention-probe | jobs:write | On-demand brand mention probe with optional query body |
curl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/properties/PROPERTY_ID/geo/settingsCompetitors & issue tasks
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /properties/:id/competitors/changes | properties:read | Recent title/meta/H1 diffs (Starter+ monitoring) |
| POST | /properties/:id/competitors/jobs/competitor-snapshot | jobs:write | Snapshot tracked rivals — optional competitorId |
| PATCH | /properties/:id/issue-tasks/:issueKey | properties:write | Assign issue to teammate with optional due date (Growth+) |
curl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/properties/PROPERTY_ID/competitors/changescurl -X PATCH -H "Authorization: Bearer xf_live_..." \
-H "Content-Type: application/json" \
-d '{"assignedToUserId":"USER_ID","dueAt":"2026-07-01T12:00:00.000Z"}' \
https://api.xenonflare.com/api/v1/properties/PROPERTY_ID/issue-tasks/ISSUE_KEYcurl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/organization/product-capabilitiesUsage
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /usage | usage:read | Current usage against plan limits |
| GET | /limits | usage:read | Plan limits for the workspace |
| GET | /rate-limits | usage:read | Live remaining read/write and org daily write counters for this API key |
Webhooks
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /webhooks | webhooks:read | List outbound webhook endpoints |
| POST | /webhooks | webhooks:write | Create endpoint — signingSecret returned once |
| PATCH | /webhooks/:id | webhooks:write | Update name, URL, events, or enabled flag |
| DELETE | /webhooks/:id | webhooks:write | Remove webhook endpoint |
| POST | /webhooks/:id/test | webhooks:write | Send a signed sample payload (test: true in body) — also available as Test in the Developer API webhooks tab |
Events: job.completed, job.failed, job.cancelled, uptime.down, uptime.recovered, ssl.expiring, ssl.invalid, dns.invalid, dns.recovered, redirect.chain, redirect.recovered, ssl.recovered, issue.resolved, keyword.rank_changed, gsc.anomaly. Verify deliveries with the X-XenonFlare-Signature header (HMAC SHA-256 over {timestamp}.{body}). Test deliveries use the same headers with test: true in the JSON body. Job events include a job object; monitoring events include a monitoring object with propertyId and siteUrl. Issue, keyword, and GSC events use top-level issue, keyword, or gsc objects. Cancelled website scans include a top-level resume object when applicable:
Webhook payload examples
{
"event": "job.cancelled",
"test": true,
"deliveredAt": "2026-06-07T12:02:00.000Z",
"resume": {
"resumeCrawlAvailable": true,
"checkpointPagesDone": 42,
"crawlMaxPages": 500
},
"job": {
"id": "000000000000000000000000",
"type": "seo-scan",
"status": "cancelled",
"propertyId": "507f1f77bcf86cd799439012"
}
}Reports
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /reports | reports:read | List active shared audit reports (non-expired links) |
| GET | /reports/:token | reports:read | Report metadata and public URL for a share token |
Reports are created in the web app when you share an audit. Each item includes a publicUrl pointing to the read-only report page on xenonflare.com. Use reports:read on keys that should list share links but not queue scans — common for client-facing dashboards and monthly reporting pipelines.
Example: list shared reports
curl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/reports?limit=20Fetch a single report with GET /reports/:token. Related: Site audit API, agency portfolio guide.
Search Console
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /organization/gsc | gsc:read | Portfolio summary — linked properties, 28-day clicks and impressions totals |
| GET | /properties/:id/gsc | gsc:read | Cached snapshot: queries, pages, daily series, crawl correlation (null when not linked) |
| GET | /properties/:id/gsc/overview | gsc:read | Connection status and 28-day totals only |
| GET | /properties/:id/gsc/queries | gsc:read | Paginated top queries from cached snapshot |
| GET | /properties/:id/gsc/pages | gsc:read | Paginated top pages from cached snapshot |
| POST | /properties/:id/gsc/sync | gsc:write | Trigger a live GSC refresh (uses org OAuth from the web app) |
GSC OAuth connect runs in the web app. Most read endpoints use stored MongoDB snapshots; POST …/gsc/sync calls Google with the linked org token.
Response format
Successful responses wrap data in a consistent envelope. Errors use the same meta.requestId.
{
"data": { },
"meta": {
"requestId": "...",
"hasMore": false,
"nextCursor": null
}
}Examples
Show JSON response samples
{
"data": {
"organization": {
"id": "507f1f77bcf86cd799439011",
"name": "Acme Marketing",
"plan": "starter"
},
"usage": { "plan": "starter", "periodLabel": "Jun 2026" },
"totals": { "properties": 3, "activeJobs": 1 }
},
"meta": { "requestId": "req_abc123" }
}Pagination
List endpoints accept limit (max 100, default 40) and cursor. When more results exist, meta.hasMore is true and meta.nextCursor contains an opaque token for the next page.
GET https://api.xenonflare.com/api/v1/properties?limit=40&cursor=opaque_tokenIdempotency
Write endpoints (POST) accept an optional Idempotency-Key header (max 128 characters). Repeating the same key within 24 hours returns the original successful response without duplicating side effects — useful for retries in CI or webhook handlers.
curl -X POST \
-H "Authorization: Bearer xf_live_..." \
-H "Idempotency-Key: scan-2026-06-07-example-com" \
https://api.xenonflare.com/api/v1/properties/PROPERTY_ID/scansFull guide: Idempotency for write requests (TTL, replay rules, CI key patterns, retry matrix).
Rate limits
Two layers apply: API rate limits (per key / per org) and plan quotas (scans, websites, crawl pages). Plan quotas are enforced on write endpoints and return 403 plan_required; API rate limits return 429 rate_limit.
| Limit | Default | Scope |
|---|---|---|
| Read requests per API key | 1,000 / hour | API rate limit |
| Write requests per API key | 60 / hour | API rate limit |
| Write requests per organization | 500 / day | API rate limit (safety net) |
| Active API keys per organization | 5 | Key cap |
| Scans / websites / crawl pages | Plan-dependent | Plan quota — see GET /limits |
Headers and live counters
Successful responses include X-Developer-Api-RateLimit-read-* or X-Developer-Api-RateLimit-write-* headers (Limit, Remaining, Reset). For programmatic backoff, call GET /rate-limits (usage:read):
curl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/rate-limitsStatic plan caps (including documented API limits) are on GET /limits under data.developerApi and data.uptime (monitoring availability, probe interval, history retention, status page caps). When exceeded, the API returns 429 with a Retry-After header (seconds until the window resets) — see the 429 response tab above.
For XenonFlare platform availability, see status.xenonflare.com. For your own monitored sites, use GET /uptime and publish customer pages via PUT /properties/:id/status-page (public URL xenonflare.com/status/{slug}). AI assistants can use the llms.txt index for a concise map of endpoints and guides.
Step-by-step
- Sign in at app.xenonflare.com on a Starter or Growth plan.
- Open Developer API in the sidebar and create a key with
properties:readandjobs:writeas needed. - List properties, queue a scan, and poll job status:
curl -H "Authorization: Bearer xf_live_..." \
https://api.xenonflare.com/api/v1/propertiesError catalog
Show full error catalog
All errors use { error: { code, message }, meta: { requestId } }.
| Code | HTTP | When | What to do |
|---|---|---|---|
api_key_invalid | 401 | Missing, malformed, or revoked Bearer token | Check header format; create or rotate key in Developer settings |
unauthorized | 401 | Developer API disabled or auth rejected | Verify plan and that Developer API is enabled for the workspace |
insufficient_scope | 403 | Key lacks required scope for the route | Create a key with the scope listed on the endpoint, or rotate with broader scopes |
forbidden | 403 | Generic access denied (non-scope) | Confirm org membership and endpoint access rules |
plan_required | 403 | Free plan, or monthly scan/website quota exhausted | Upgrade plan or wait for billing period reset; check GET /usage |
rate_limit | 429 | API read/write or org daily write cap exceeded | Backoff until reset; use GET /rate-limits or rate-limit headers |
not_found | 404 | Property, job, webhook, or report not in this org | Verify ID belongs to the keyed organization |
validation_error | 400 | Invalid body, query param, or business rule (e.g. cancel completed job) | Fix request per message; use new idempotency key if body changed |
internal_error | 500 | Unexpected server failure | Retry with backoff; contact support with meta.requestId |
SDK & code generation
Show OpenAPI Generator commands
Generate a typed client from the OpenAPI spec with OpenAPI Generator. Replace the output directory with your project path.
npx @openapitools/openapi-generator-cli generate \
-i https://xenonflare.com/openapi/developer-v1.yaml \
-g typescript-fetch \
-o ./src/generated/xenonflare-apiPass your key on every request: Authorization: Bearer xf_live_…. For local development, point -i at http://localhost:4000/openapi/developer-v1.yaml or the copy in this repo.
OpenAPI
Machine-readable specification for code generation and API clients: developer-v1.yaml (OpenAPI 3.1). Download from the quickstart panel above or import into your preferred API client.
Developer API