Developers
REST API
The API lives at https://index365.co/api/v1. The machine-readable reference is published at /openapi.json with agent-grade operation descriptions, examples, and error codes.
Authentication
Send your key in the Authorization header. Query-string tokens are rejected by design.
curl -s https://index365.co/api/v1/me \
-H "Authorization: Bearer i365_..."GET /api/v1/me works with any valid key and returns your organization, scopes, and the contract version. Call it first in any integration.
Scopes
projects:read,runs:read,findings:read,reports:read: the default read-only set every key gets.runs:write: start audits. Spends organization credits, so grant it deliberately.webhooks:manage: create, update, and delete webhook endpoints.
Start an audit and read the results
# 1. Find your project
curl -s "https://index365.co/api/v1/projects" -H "Authorization: Bearer $KEY"
# 2. Start the audit (202 returns the run immediately; retry-safe via Idempotency-Key)
curl -s -X POST "https://index365.co/api/v1/runs" \
-H "Authorization: Bearer $KEY" \
-H "Idempotency-Key: deploy-42" \
-H "Content-Type: application/json" \
-d '{"projectId":"<projectId>"}'
# 3. Poll until status is terminal (or subscribe to run.completed webhooks)
curl -s "https://index365.co/api/v1/runs/<runId>" -H "Authorization: Bearer $KEY"
# 4. Read the compact report context first, then page through findings
curl -s "https://index365.co/api/v1/runs/<runId>/report" -H "Authorization: Bearer $KEY"
curl -s "https://index365.co/api/v1/runs/<runId>/findings?severity=critical" \
-H "Authorization: Bearer $KEY"Marketing Signal audits
# Start a Marketing Signal run (same endpoint, scanMode picks the product)
curl -s -X POST "https://index365.co/api/v1/runs" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"projectId":"<projectId>","scanMode":"paid_marketing_signal"}'
# Latest Marketing Signal report for a project (stage scores + source coverage)
curl -s "https://index365.co/api/v1/projects/<projectId>/marketing/report" \
-H "Authorization: Bearer $KEY"
# Connected-signal providers and per-project status (planned until they launch)
curl -s "https://index365.co/api/v1/projects/<projectId>/integrations" \
-H "Authorization: Bearer $KEY"Marketing Signal findings flow through the same findings endpoints and carry an extra stage field (find, trust, act, measure, improve). The report context names its evidence base via sourceCoverage: public signals today, connected sources when account integrations launch.
The agent result contract
Findings are served as contract v2: stable findingId, a category, severity and confidence, an evidence array, affectedUrls, remediation text, agentActions, timestamps, provenance (scan mode and model), and a humanUrl that links your teammates to the same data in the dashboard. Completed runs are immutable, so finding ids and report payloads are safe to cache and reference across sessions.
Pagination, caching, and rate limits
- List endpoints are cursor-paginated: pass
cursorfrom the previouspagination.nextCursoruntil it is null.limitcaps at 100. - Completed runs return cacheable responses; in-flight runs are
no-store. Poll roughly every 10 seconds. - 60 requests per minute per key. A 429 includes
Retry-After.
Errors
Every error is JSON: {"error":{"code":"...","message":"..."}}. Codes you should handle: unauthorized (401), insufficient_scope (403), not_found (404), insufficient_credits and no_active_subscription (402), run_in_flight (409), rate_limited (429).
Security model
- Key secrets are stored as sha256 hashes; only the prefix is retrievable.
- Every request is scoped to the key's organization server-side. Object ids from other organizations return 404.
- Keys are read-only unless you grant write scopes, and revoke instantly.
- Every API request lands in an audit log with method, path, and status.