{"openapi":"3.0.3","info":{"title":"HyreLog API","version":"1.0.0","description":"HyreLog API reference. Authenticate with Bearer API key for /v1/* routes."},"components":{"schemas":{}},"paths":{"/health":{"get":{"summary":"Health check","tags":["System"],"description":"Returns service health. No authentication required.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"Service is healthy"}},"required":["ok"]}}}}}}},"/v1/events":{"post":{"summary":"Ingest event","tags":["Events"],"description":"Ingest an audit event. Requires Bearer API key (workspace scope). Idempotent when idempotencyKey is provided.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["category","action"],"properties":{"timestamp":{"type":"string","format":"date-time","description":"Event time (ISO 8601). Defaults to server time."},"projectId":{"type":"string","format":"uuid","description":"Project ID if scoped to a project"},"category":{"type":"string","minLength":1,"description":"Event category"},"action":{"type":"string","minLength":1,"description":"Event action"},"actor":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string"}}},"resource":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"}}},"metadata":{"type":"object","additionalProperties":true,"description":"Arbitrary key-value data"},"idempotencyKey":{"type":"string","description":"Key for idempotent ingestion; duplicate requests return 200 with existing event"}}}}},"required":true},"responses":{"200":{"description":"Idempotent replay – existing event returned","content":{"application/json":{"schema":{"type":"object","description":"Idempotent replay – existing event returned","properties":{"id":{"type":"string"}},"required":["id"]}}}},"201":{"description":"Created event","content":{"application/json":{"schema":{"type":"object","description":"Created event","properties":{"id":{"type":"string","description":"Event ID"}},"required":["id"]}}}}}},"get":{"summary":"Query events","tags":["Events"],"description":"List audit events with optional filters and cursor pagination. Requires Bearer API key (workspace or company scope).","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"in":"query","name":"limit","required":false,"description":"Max events per page"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Opaque cursor for next page"},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"from","required":false,"description":"Filter events from this time (ISO 8601)"},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"to","required":false,"description":"Filter events until this time (ISO 8601)"},{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Filter by category"},{"schema":{"type":"string"},"in":"query","name":"action","required":false,"description":"Filter by action"},{"schema":{"type":"string","format":"uuid"},"in":"query","name":"projectId","required":false,"description":"Filter by project"},{"schema":{"type":"string","format":"uuid"},"in":"query","name":"workspaceId","required":false,"description":"Filter by workspace (company keys only)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"List of audit events"},"nextCursor":{"type":["null","string"],"description":"Cursor for next page, or null"}},"required":["data","nextCursor"]}}}}}}},"/v1/workspaces/{workspaceId}/keys":{"post":{"summary":"Create API key (dashboard only)","tags":["API Keys"],"description":"Key creation is only available via the dashboard. Use the dashboard to create and copy API keys.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"workspaceId","required":true}],"responses":{"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}}}}},"/v1/keys/{keyId}/rotate":{"post":{"summary":"Rotate API key (dashboard only)","tags":["API Keys"],"description":"Key rotation is only available via the dashboard. Use the dashboard to rotate keys and update your app with the new key.","parameters":[{"schema":{"type":"string"},"in":"path","name":"keyId","required":true}],"responses":{"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}}}}}}}},"/v1/keys/status":{"get":{"summary":"Get API key status","tags":["API Keys"],"description":"Returns the status and metadata of the API key used for this request.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"prefix":{"type":"string"},"scope":{"type":"string","enum":["COMPANY","WORKSPACE"]},"status":{"type":"string"},"expiresAt":{"type":["null","string"],"format":"date-time"},"lastUsedAt":{"type":["null","string"],"format":"date-time"},"lastUsedIp":{"type":["null","string"]},"lastUsedEndpoint":{"type":["null","string"]},"healthScore":{"type":"integer"}},"required":["id","prefix","scope","status","healthScore"]}}}}}}},"/v1/workspaces/{workspaceId}/webhooks":{"post":{"summary":"Create webhook","tags":["Webhooks"],"description":"Create a webhook endpoint for a workspace. Requires company-scoped API key and IP allowlist. Webhooks require Pro plan or higher.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook endpoint URL (HTTPS in production)"},"events":{"type":"array","items":{"type":"string","enum":["AUDIT_EVENT_CREATED"]},"description":"Events to subscribe to; default: AUDIT_EVENT_CREATED"},"projectId":{"type":["string","null"],"format":"uuid","description":"Scope to project; null for workspace-wide"},"secretLabel":{"type":"string","description":"Optional label for the secret"}}}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"workspaceId","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"projectId":{"type":["null","string"]},"secret":{"type":"string","description":"Shown only once; store securely"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","status","secret","createdAt"]}}}}}},"get":{"summary":"List webhooks","tags":["Webhooks"],"description":"List webhook endpoints for a workspace. Requires company-scoped API key.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"workspaceId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"webhooks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"projectId":{"type":["null","string"]},"lastSuccessAt":{"type":["null","string"],"format":"date-time"},"lastFailureAt":{"type":["null","string"],"format":"date-time"},"failureCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}},"required":["webhooks"]}}}}}}},"/v1/webhooks/{webhookId}/disable":{"post":{"summary":"Disable webhook","tags":["Webhooks"],"description":"Disable a webhook endpoint. Requires company-scoped API key and IP allowlist.","parameters":[{"schema":{"type":"string"},"in":"path","name":"webhookId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status"]}}}}}}},"/v1/webhooks/{webhookId}/enable":{"post":{"summary":"Enable webhook","tags":["Webhooks"],"description":"Re-enable a disabled webhook. Requires company-scoped API key and IP allowlist.","parameters":[{"schema":{"type":"string"},"in":"path","name":"webhookId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status"]}}}}}}},"/v1/webhooks/{webhookId}/deliveries":{"get":{"summary":"List webhook deliveries","tags":["Webhooks"],"description":"List delivery attempts for a webhook with optional filters. Requires company-scoped API key.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","enum":["PENDING","SENDING","SUCCEEDED","FAILED","RETRY_SCHEDULED"]},"in":"query","name":"status","required":false},{"schema":{"type":"string"},"in":"path","name":"webhookId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":["null","string"]}},"required":["data","nextCursor"]}}}}}}},"/v1/exports":{"post":{"summary":"Create export job","tags":["Exports"],"description":"Create a streaming export job. Requires Starter plan or higher. ARCHIVED/HOT_AND_ARCHIVED require from/to filters and may require archive restoration.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["source","format"],"properties":{"source":{"type":"string","enum":["HOT","ARCHIVED","HOT_AND_ARCHIVED"],"description":"Data source for export"},"format":{"type":"string","enum":["JSONL","CSV"],"description":"Output format"},"filters":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"category":{"type":"string"},"action":{"type":"string"},"workspaceId":{"type":"string","format":"uuid"},"projectId":{"type":"string","format":"uuid"}},"description":"Optional filters; from/to required for ARCHIVED"},"limit":{"type":"integer","description":"Max rows (plan-limited)"}}}}},"required":true},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"status":{"type":"string"}},"required":["jobId","status"]}}}}}}},"/v1/exports/{jobId}":{"get":{"summary":"Get export job status","tags":["Exports"],"description":"Get status and metadata for an export job.","parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"source":{"type":"string"},"format":{"type":"string"},"rowLimit":{"type":"string"},"rowsExported":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["null","string"],"format":"date-time"},"finishedAt":{"type":["null","string"],"format":"date-time"},"errorCode":{"type":["null","string"]},"errorMessage":{"type":["null","string"]}},"required":["id","status","source","format","rowsExported","createdAt"]}}}}}}},"/v1/exports/{jobId}/download":{"get":{"summary":"Download export","tags":["Exports"],"description":"Stream export data (JSONL or CSV). Content-Type and Content-Disposition set on response. Job must be in PENDING or RUNNING state.","parameters":[{"schema":{"type":"string"},"in":"path","name":"jobId","required":true}],"responses":{"200":{"description":"Stream of export data (application/x-ndjson or text/csv). Use GET after job is created; response is streamed.","content":{"application/json":{"schema":{"description":"Stream of export data (application/x-ndjson or text/csv). Use GET after job is created; response is streamed.","type":"string"}}}}}}},"/":{"get":{"responses":{"200":{"description":"Default Response"}}}}},"servers":[{"url":"https://api.hyrelog.com","description":"Production"}]}