{"openapi":"3.1.0","info":{"title":"Edgify API","version":"0.1.0","description":"Edgify is edge-first virtual API key infrastructure. This spec covers every\nHTTP endpoint across the 5 apps. Each operation is tagged with `x-edgify-served-by`\nindicating which app implements it.\n\nServers:\n- `https://api.edgify.net` — control-worker (data plane CRUD)\n- `https://edgify.net` — backend-laravel (auth, billing, admin)\n- `https://proxy.edgify.net` — proxy-worker (catch-all forwarding; not fully described here)\n","contact":{"email":"support@edgify.net"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://edgify.net","description":"Production — Laravel backend","x-edgify-served-by":"laravel"},{"url":"https://api.edgify.net","description":"Production — control-worker","x-edgify-served-by":"control-worker"},{"url":"http://localhost:8000","description":"Local dev — Laravel","x-edgify-served-by":"laravel"},{"url":"http://localhost:8787","description":"Local dev — control-worker","x-edgify-served-by":"control-worker"}],"tags":[{"name":"auth","description":"Authentication & session","x-edgify-served-by":"laravel"},{"name":"me","description":"Current user","x-edgify-served-by":"laravel"},{"name":"organizations","description":"Organization settings & team","x-edgify-served-by":"laravel"},{"name":"subscriptions","description":"Billing & plans","x-edgify-served-by":"laravel"},{"name":"plans","description":"Public plan catalog","x-edgify-served-by":"laravel"},{"name":"provider-keys","description":"Master provider credentials","x-edgify-served-by":"control-worker"},{"name":"virtual-keys","description":"Issued sub-keys","x-edgify-served-by":"control-worker"},{"name":"limit-profiles","description":"Hierarchical policy rules","x-edgify-served-by":"control-worker"},{"name":"usage","description":"Usage queries","x-edgify-served-by":"control-worker"},{"name":"alerts","description":"Alert rules & fired events","x-edgify-served-by":"control-worker"},{"name":"webhooks","description":"Webhook endpoints","x-edgify-served-by":"control-worker"},{"name":"audit","description":"Audit logs","x-edgify-served-by":"control-worker"},{"name":"enterprise-sso","description":"SSO configuration (Phase 7)","x-edgify-served-by":"laravel"},{"name":"enterprise-scim","description":"SCIM 2.0 provisioning (Phase 7)","x-edgify-served-by":"laravel"},{"name":"enterprise-service-accounts","description":"Programmatic identities (Phase 7)","x-edgify-served-by":"laravel"},{"name":"enterprise-roles","description":"Custom RBAC (Phase 7)","x-edgify-served-by":"laravel"},{"name":"internal","description":"Internal endpoints (worker-to-worker only)","x-edgify-served-by":"control-worker"}],"security":[{"bearerAuth":[]}],"paths":{"/api/register":{"post":{"tags":["auth"],"summary":"Register a new user + organization","operationId":"register","security":[],"x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"422":{"$ref":"#/components/responses/ValidationError"}}}},"/api/login":{"post":{"tags":["auth"],"summary":"Log in with email + password","operationId":"login","security":[],"x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/logout":{"post":{"tags":["auth"],"summary":"Log out (revoke current JWT)","operationId":"logout","x-edgify-served-by":"laravel","responses":{"204":{"description":"No content"}}}},"/api/auth/refresh":{"post":{"tags":["auth"],"summary":"Exchange refresh token for new access token","operationId":"refresh","security":[],"x-edgify-served-by":"laravel","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}}}}},"/api/auth/password-reset/request":{"post":{"tags":["auth"],"summary":"Request a password reset email","operationId":"passwordResetRequest","security":[],"x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}},"responses":{"204":{"description":"No content"}}}},"/api/auth/password-reset/confirm":{"post":{"tags":["auth"],"summary":"Confirm password reset with token","operationId":"passwordResetConfirm","security":[],"x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"new_password":{"type":"string","minLength":12}},"required":["token","new_password"]}}}},"responses":{"204":{"description":"No content"}}}},"/api/me":{"get":{"tags":["me"],"summary":"Get current user","operationId":"me","x-edgify-served-by":"laravel","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}},"patch":{"tags":["me"],"summary":"Update current user profile","operationId":"updateMe","x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}}},"/api/me/export":{"post":{"tags":["me"],"summary":"Request a GDPR data export (async)","operationId":"exportMyData","x-edgify-served-by":"laravel","responses":{"202":{"description":"Accepted; download link will be emailed within 30 days","content":{"application/json":{"schema":{"type":"object","properties":{"job_id":{"type":"string"}}}}}}}}},"/api/me/delete":{"post":{"tags":["me"],"summary":"Anonymize current user (GDPR right to erasure)","operationId":"deleteMe","x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","enum":["DELETE"]}},"required":["confirm"]}}}},"responses":{"204":{"description":"No content"}}}},"/api/organizations/current":{"get":{"tags":["organizations"],"summary":"Get current organization","operationId":"getCurrentOrg","x-edgify-served-by":"laravel","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}}}},"patch":{"tags":["organizations"],"summary":"Update current organization","operationId":"updateCurrentOrg","x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationUpdate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Organization"}}}}}}},"/api/organizations/current/members":{"get":{"tags":["organizations"],"summary":"List org members","operationId":"listMembers","x-edgify-served-by":"laravel","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}}},"/api/organizations/current/members/invite":{"post":{"tags":["organizations"],"summary":"Invite a new member","operationId":"inviteMember","x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["admin","developer","billing_viewer","auditor"]}},"required":["email","role"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitation"}}}}}}},"/api/teams/invitations/accept":{"post":{"tags":["organizations"],"summary":"Accept a team invitation","operationId":"acceptInvitation","security":[],"x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}}}}},"/api/organizations/current/delete":{"post":{"tags":["organizations"],"summary":"Schedule organization deletion (owner only)","operationId":"deleteOrg","x-edgify-served-by":"laravel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","enum":["DELETE"]},"feedback":{"type":"string"}},"required":["confirm"]}}}},"responses":{"204":{"description":"No content"}}}},"/api/plans":{"get":{"tags":["plans"],"summary":"List public plans","operationId":"listPlans","security":[],"x-edgify-served-by":"laravel","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Plan"}}}}}}}},"/api/subscriptions/current":{"get":{"tags":["subscriptions"],"summary":"Get current subscription","operationId":"getCurrentSubscription","x-edgify-served-by":"laravel","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}}}}},"/api/subscriptions/current/checkout-session":{"post":{"tags":["subscriptions"],"summary":"Create Stripe Checkout session","operationId":"createCheckoutSession","x-edgify-served-by":"laravel","x-edgify-status":"deferred-until-blocker-004","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan_slug":{"type":"string"}},"required":["plan_slug"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}}}}},"/api/subscriptions/current/portal-session":{"post":{"tags":["subscriptions"],"summary":"Create Stripe Customer Portal session","operationId":"createPortalSession","x-edgify-served-by":"laravel","x-edgify-status":"deferred-until-blocker-004","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}}}}},"/webhooks/stripe":{"post":{"tags":["subscriptions"],"summary":"Stripe webhook handler","operationId":"stripeWebhook","security":[],"x-edgify-served-by":"laravel","x-edgify-status":"deferred-until-blocker-004","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK"}}}},"/api/provider-keys":{"get":{"tags":["provider-keys"],"summary":"List provider keys","operationId":"listProviderKeys","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderKey"}}}}}}},"post":{"tags":["provider-keys"],"summary":"Create a provider key","operationId":"createProviderKey","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyCreate"}}}},"responses":{"201":{"description":"Created — secret returned ONCE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyWithSecret"}}}}}}},"/api/provider-keys/{id}":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["provider-keys"],"summary":"Get provider key","operationId":"getProviderKey","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKey"}}}}}},"patch":{"tags":["provider-keys"],"summary":"Update provider key","operationId":"updateProviderKey","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyUpdate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKey"}}}}}},"delete":{"tags":["provider-keys"],"summary":"Archive (soft-delete) provider key","operationId":"deleteProviderKey","x-edgify-served-by":"control-worker","responses":{"204":{"description":"No content"}}}},"/api/provider-keys/{id}/rotate":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["provider-keys"],"summary":"Rotate a provider key","operationId":"rotateProviderKey","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"new_secret":{"type":"string"}},"required":["new_secret"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKey"}}}}}}},"/api/virtual-keys":{"get":{"tags":["virtual-keys"],"summary":"List virtual keys","operationId":"listVirtualKeys","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["active","revoked","expired","pending_approval"]}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"in":"query","name":"cursor","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKeyList"}}}}}},"post":{"tags":["virtual-keys"],"summary":"Create a virtual key","operationId":"createVirtualKey","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKeyCreate"}}}},"responses":{"201":{"description":"Created — token returned ONCE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKeyWithToken"}}}}}}},"/api/virtual-keys/{id}":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["virtual-keys"],"summary":"Get virtual key","operationId":"getVirtualKey","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKey"}}}}}},"patch":{"tags":["virtual-keys"],"summary":"Update virtual key","operationId":"updateVirtualKey","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKeyUpdate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKey"}}}}}},"delete":{"tags":["virtual-keys"],"summary":"Delete virtual key (hard delete)","operationId":"deleteVirtualKey","x-edgify-served-by":"control-worker","responses":{"204":{"description":"No content"}}}},"/api/virtual-keys/{id}/revoke":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["virtual-keys"],"summary":"Revoke virtual key","operationId":"revokeVirtualKey","x-edgify-served-by":"control-worker","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirtualKey"}}}}}}},"/api/limit-profiles":{"get":{"tags":["limit-profiles"],"summary":"List limit profiles","operationId":"listLimitProfiles","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LimitProfile"}}}}}}},"post":{"tags":["limit-profiles"],"summary":"Create limit profile","operationId":"createLimitProfile","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitProfileCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitProfile"}}}}}}},"/api/limit-profiles/{id}":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["limit-profiles"],"summary":"Get limit profile","operationId":"getLimitProfile","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitProfile"}}}}}},"patch":{"tags":["limit-profiles"],"summary":"Update limit profile","operationId":"updateLimitProfile","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitProfileUpdate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitProfile"}}}}}},"delete":{"tags":["limit-profiles"],"summary":"Delete limit profile","operationId":"deleteLimitProfile","x-edgify-served-by":"control-worker","responses":{"204":{"description":"No content"}}}},"/api/usage/summary":{"get":{"tags":["usage"],"summary":"Org usage summary","operationId":"usageSummary","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date"}},{"in":"query","name":"to","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}}}}},"/api/usage/events":{"get":{"tags":["usage"],"summary":"Paginated usage events","operationId":"usageEvents","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"virtual_key_id","schema":{"type":"string","format":"uuid"}},{"in":"query","name":"from","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"to","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"blocked","schema":{"type":"boolean"}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"in":"query","name":"cursor","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageEventList"}}}}}}},"/api/usage/by-key":{"get":{"tags":["usage"],"summary":"Usage by key","operationId":"usageByKey","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date"}},{"in":"query","name":"to","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"virtual_key_id":{"type":"string"},"name":{"type":"string"},"requests":{"type":"integer"},"cost_usd":{"type":"number"}}}}}}}}}},"/api/usage/by-user":{"get":{"tags":["usage"],"summary":"Usage by user","operationId":"usageByUser","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date"}},{"in":"query","name":"to","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"email":{"type":"string"},"requests":{"type":"integer"},"cost_usd":{"type":"number"}}}}}}}}}},"/api/usage/by-cost-center":{"get":{"tags":["usage"],"summary":"Usage by cost center (Phase 10)","operationId":"usageByCostCenter","x-edgify-served-by":"control-worker","x-edgify-status":"phase-10","parameters":[{"in":"query","name":"period","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/alerts":{"get":{"tags":["alerts"],"summary":"List alert rules","operationId":"listAlertRules","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlertRule"}}}}}}},"post":{"tags":["alerts"],"summary":"Create alert rule","operationId":"createAlertRule","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRule"}}}}}}},"/api/alerts/{id}":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["alerts"],"summary":"Update alert rule","operationId":"updateAlertRule","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleUpdate"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRule"}}}}}},"delete":{"tags":["alerts"],"summary":"Delete alert rule","operationId":"deleteAlertRule","x-edgify-served-by":"control-worker","responses":{"204":{"description":"No content"}}}},"/api/alerts/events":{"get":{"tags":["alerts"],"summary":"Fired alert events","operationId":"listAlertEvents","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"acknowledged","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlertEvent"}}}}}}}},"/api/alerts/events/{id}/acknowledge":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["alerts"],"summary":"Acknowledge a fired alert","operationId":"acknowledgeAlert","x-edgify-served-by":"control-worker","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertEvent"}}}}}}},"/api/alerts/stream":{"get":{"tags":["alerts"],"summary":"SSE stream of real-time alert events","operationId":"alertsStream","x-edgify-served-by":"control-worker","responses":{"200":{"description":"text/event-stream","content":{"text/event-stream":{"schema":{"type":"string"}}}}}}},"/api/webhook-endpoints":{"get":{"tags":["webhooks"],"summary":"List webhook endpoints","operationId":"listWebhookEndpoints","x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}}},"post":{"tags":["webhooks"],"summary":"Create webhook endpoint","operationId":"createWebhookEndpoint","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}}}}}},"/api/webhook-endpoints/{id}":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"}}],"patch":{"tags":["webhooks"],"summary":"Update webhook endpoint","operationId":"updateWebhookEndpoint","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"enabled":{"type":"boolean"},"event_types":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"delete":{"tags":["webhooks"],"summary":"Delete webhook endpoint","operationId":"deleteWebhookEndpoint","x-edgify-served-by":"control-worker","responses":{"204":{"description":"No content"}}}},"/api/webhook-deliveries":{"get":{"tags":["webhooks"],"summary":"List webhook deliveries","operationId":"listWebhookDeliveries","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["pending","success","retrying","dead_letter"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}}}},"/api/audit-logs":{"get":{"tags":["audit"],"summary":"List audit log entries","operationId":"listAuditLogs","x-edgify-served-by":"control-worker","parameters":[{"in":"query","name":"actor_id","schema":{"type":"string","format":"uuid"}},{"in":"query","name":"action","schema":{"type":"string"}},{"in":"query","name":"from","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"to","schema":{"type":"string","format":"date-time"}},{"in":"query","name":"limit","schema":{"type":"integer","default":100}},{"in":"query","name":"cursor","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogList"}}}}}}},"/api/audit-logs/export":{"post":{"tags":["audit"],"summary":"Export audit logs (async)","operationId":"exportAuditLogs","x-edgify-served-by":"control-worker","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"format":{"type":"string","enum":["csv","jsonl"]}},"required":["from","to","format"]}}}},"responses":{"202":{"description":"Accepted; download link emailed","content":{"application/json":{"schema":{"type":"object","properties":{"job_id":{"type":"string"}}}}}}}}},"/api/proxy/auth":{"post":{"tags":["internal"],"summary":"Validate virtual key and return policy snapshot","operationId":"proxyAuth","security":[{"internalSharedSecret":[]}],"x-edgify-served-by":"control-worker","x-edgify-internal":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key_id":{"type":"string","format":"uuid"}},"required":["key_id"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicySnapshot"}}}},"404":{"description":"Key not found"}}}},"/api/proxy/log":{"post":{"tags":["internal"],"summary":"Ingest usage event (fallback when Cloudflare Queues unavailable)","operationId":"proxyLog","security":[{"internalSharedSecret":[]}],"x-edgify-served-by":"control-worker","x-edgify-internal":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageEvent"}}}},"responses":{"202":{"description":"Accepted"}}}},"/healthz":{"get":{"tags":["internal"],"summary":"Healthcheck","operationId":"healthz","security":[],"x-edgify-served-by":"control-worker","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"version":{"type":"string"}}}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"internalSharedSecret":{"type":"apiKey","in":"header","name":"X-Edgify-Internal"}},"schemas":{"UUID":{"type":"string","format":"uuid"},"RegisterRequest":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":12},"name":{"type":"string"},"organization_name":{"type":"string","description":"Display name for the new organization — slug is derived server-side."},"use_case":{"type":"string","nullable":true,"description":"Optional free-text from the wizard's step 2."},"plan":{"type":"string","nullable":true,"description":"Plan slug captured at sign-up. Pricing/limits are applied separately by the billing flow.","enum":["evaluate","team","scale","enterprise"]}},"required":["email","password","name","organization_name"]},"LoginRequest":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"}},"required":["email","password"]},"AuthResponse":{"type":"object","description":"Returned by /api/register, /api/login, and /api/auth/refresh.\nTokens appear both at the top level (so the React AuthContext can\nread `access_token` directly) and inside `tokens` (for clients that\nprefer the structured form).\n","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer"},"user":{"$ref":"#/components/schemas/User"},"organization":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"name":{"type":"string"},"slug":{"type":"string"}}},"tokens":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"expires_in":{"type":"integer"},"token_type":{"type":"string","enum":["Bearer"]}}}},"required":["access_token","token_type","expires_in"]},"User":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"organization_id":{"$ref":"#/components/schemas/UUID"},"email":{"type":"string","format":"email"},"name":{"type":"string"},"role":{"type":"string","enum":["owner","admin","developer","billing_viewer","auditor"]},"custom_role_id":{"$ref":"#/components/schemas/UUID"},"auth_provider":{"type":"string","enum":["password","oidc","saml","magic_link"]},"mfa_enabled":{"type":"boolean"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Organization":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"name":{"type":"string"},"slug":{"type":"string"},"billing_email":{"type":"string"},"region_preference":{"type":"string"},"plan_id":{"$ref":"#/components/schemas/UUID"},"subscription_status":{"type":"string"},"data_retention_days_usage":{"type":"integer"},"data_retention_days_audit":{"type":"integer"},"pii_redaction_enabled":{"type":"boolean"},"full_body_logging_enabled":{"type":"boolean"},"sso_enabled":{"type":"boolean"},"custom_domain":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"OrganizationUpdate":{"type":"object","properties":{"name":{"type":"string"},"billing_email":{"type":"string"},"region_preference":{"type":"string"},"data_retention_days_usage":{"type":"integer"},"pii_redaction_enabled":{"type":"boolean"}}},"TeamInvitation":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"email":{"type":"string"},"role":{"type":"string"},"expires_at":{"type":"string","format":"date-time"}}},"Plan":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"slug":{"type":"string"},"display_name":{"type":"string"},"tier":{"type":"integer"},"monthly_price_usd":{"type":"number"},"included_requests":{"type":"integer"},"included_keys":{"type":"integer"},"included_users":{"type":"integer"},"features":{"type":"object"},"overage_rate_usd_per_1k_requests":{"type":"number"}}},"Subscription":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"plan":{"$ref":"#/components/schemas/Plan"},"status":{"type":"string","enum":["trialing","active","past_due","canceled","frozen"]},"current_period_start":{"type":"string","format":"date-time"},"current_period_end":{"type":"string","format":"date-time"},"trial_ends_at":{"type":"string","format":"date-time","nullable":true},"cancel_at_period_end":{"type":"boolean"}}},"ProviderKey":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"name":{"type":"string"},"provider":{"type":"string","enum":["openai","anthropic","openrouter","cloudflare_ai","custom_http"]},"secret_last_four":{"type":"string"},"base_url":{"type":"string","nullable":true},"status":{"type":"string","enum":["active","disabled","rotating"]},"last_used_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"ProviderKeyCreate":{"type":"object","properties":{"name":{"type":"string"},"provider":{"type":"string"},"secret":{"type":"string"},"base_url":{"type":"string","nullable":true},"default_headers":{"type":"object"}},"required":["name","provider","secret"]},"ProviderKeyUpdate":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"base_url":{"type":"string"},"default_headers":{"type":"object"}}},"ProviderKeyWithSecret":{"allOf":[{"$ref":"#/components/schemas/ProviderKey"},{"type":"object","properties":{"secret_one_time":{"type":"string","description":"ONLY returned at creation. Save it; it will never be returned again."}}}]},"VirtualKey":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"organization_id":{"$ref":"#/components/schemas/UUID"},"user_id":{"$ref":"#/components/schemas/UUID"},"provider_key_id":{"$ref":"#/components/schemas/UUID"},"name":{"type":"string"},"prefix":{"type":"string"},"status":{"type":"string","enum":["active","revoked","expired","pending_approval"]},"expires_at":{"type":"string","format":"date-time","nullable":true},"limit_profile_id":{"$ref":"#/components/schemas/UUID"},"allowed_origins":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object"},"cost_center":{"type":"string","nullable":true},"caching_enabled":{"type":"boolean"},"last_used_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"revoked_at":{"type":"string","format":"date-time","nullable":true}}},"VirtualKeyCreate":{"type":"object","properties":{"name":{"type":"string"},"provider_key_id":{"$ref":"#/components/schemas/UUID"},"limit_profile_id":{"$ref":"#/components/schemas/UUID"},"user_id":{"$ref":"#/components/schemas/UUID"},"expires_at":{"type":"string","format":"date-time"},"allowed_origins":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object"},"cost_center":{"type":"string"},"env":{"type":"string","enum":["live","test"],"default":"live"}},"required":["name","provider_key_id"]},"VirtualKeyUpdate":{"type":"object","properties":{"name":{"type":"string"},"limit_profile_id":{"$ref":"#/components/schemas/UUID"},"expires_at":{"type":"string","format":"date-time"},"allowed_origins":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object"},"cost_center":{"type":"string"}}},"VirtualKeyWithToken":{"allOf":[{"$ref":"#/components/schemas/VirtualKey"},{"type":"object","properties":{"token_one_time":{"type":"string","description":"ONLY returned at creation. Format: edg_{env}_{keyId}_{secret}"}}}]},"VirtualKeyList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VirtualKey"}},"next_cursor":{"type":"string","nullable":true}}},"LimitProfile":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"name":{"type":"string"},"description":{"type":"string"},"scope":{"type":"string","enum":["organization","user","key","request"]},"rules":{"$ref":"#/components/schemas/LimitRules"},"created_at":{"type":"string","format":"date-time"}}},"LimitProfileCreate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"scope":{"type":"string"},"rules":{"$ref":"#/components/schemas/LimitRules"}},"required":["name","scope","rules"]},"LimitProfileUpdate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"rules":{"$ref":"#/components/schemas/LimitRules"}}},"LimitRules":{"type":"object","properties":{"requests_per_minute":{"type":"integer"},"requests_per_hour":{"type":"integer"},"requests_per_day":{"type":"integer"},"monthly_request_count":{"type":"integer"},"daily_budget_usd":{"type":"number"},"monthly_budget_usd":{"type":"number"},"max_request_bytes":{"type":"integer"},"max_response_bytes":{"type":"integer"},"max_tokens_per_request":{"type":"integer"},"allowed_methods":{"type":"array","items":{"type":"string"}},"allowed_paths":{"type":"array","items":{"type":"string"}},"blocked_paths":{"type":"array","items":{"type":"string"}},"allowed_models":{"type":"array","items":{"type":"string"}},"blocked_models":{"type":"array","items":{"type":"string"}},"allowed_origins":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"blocked_ips":{"type":"array","items":{"type":"string"}},"custom_rules":{"type":"array","items":{"type":"object"}}}},"UsageSummary":{"type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"}}},"totals":{"type":"object","properties":{"requests":{"type":"integer"},"cost_usd":{"type":"number"},"tokens_input":{"type":"integer"},"tokens_output":{"type":"integer"},"errors":{"type":"integer"}}},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"requests":{"type":"integer"},"cost_usd":{"type":"number"}}}}}},"UsageEvent":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"occurred_at":{"type":"string","format":"date-time"},"virtual_key_id":{"$ref":"#/components/schemas/UUID"},"user_id":{"$ref":"#/components/schemas/UUID"},"provider_key_id":{"$ref":"#/components/schemas/UUID"},"provider":{"type":"string"},"model":{"type":"string"},"method":{"type":"string"},"path":{"type":"string"},"status_code":{"type":"integer"},"latency_ms":{"type":"integer"},"request_bytes":{"type":"integer"},"response_bytes":{"type":"integer"},"tokens_input":{"type":"integer","nullable":true},"tokens_output":{"type":"integer","nullable":true},"cost_usd_estimated":{"type":"number"},"cache_hit":{"type":"boolean"},"client_ip":{"type":"string"},"client_country":{"type":"string"},"blocked":{"type":"boolean"},"blocked_reason":{"type":"string"},"cost_center":{"type":"string"},"metadata":{"type":"object"}}},"UsageEventList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageEvent"}},"next_cursor":{"type":"string","nullable":true}}},"AlertRule":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"name":{"type":"string"},"description":{"type":"string"},"scope":{"type":"string"},"scope_id":{"$ref":"#/components/schemas/UUID"},"trigger_type":{"type":"string","enum":["threshold_percent","threshold_absolute","anomaly_zscore","event"]},"trigger_config":{"type":"object"},"channels":{"type":"array","items":{"type":"string"}},"action":{"type":"string","enum":["notify_only","throttle","block_key","block_model","freeze_user","freeze_org"]},"cooldown_minutes":{"type":"integer"},"enabled":{"type":"boolean"}}},"AlertRuleCreate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"scope":{"type":"string"},"scope_id":{"$ref":"#/components/schemas/UUID"},"trigger_type":{"type":"string"},"trigger_config":{"type":"object"},"channels":{"type":"array","items":{"type":"string"}},"email_recipients":{"type":"array","items":{"type":"string"}},"webhook_url":{"type":"string"},"action":{"type":"string"},"cooldown_minutes":{"type":"integer"}},"required":["name","scope","trigger_type","trigger_config","channels","action"]},"AlertRuleUpdate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"trigger_config":{"type":"object"},"channels":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"}}},"AlertEvent":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"occurred_at":{"type":"string","format":"date-time"},"rule_id":{"$ref":"#/components/schemas/UUID"},"triggered_value":{"type":"number"},"threshold_value":{"type":"number"},"action_taken":{"type":"string"},"notification_status":{"type":"object"},"acknowledged_at":{"type":"string","format":"date-time","nullable":true},"acknowledged_by_user_id":{"$ref":"#/components/schemas/UUID"},"payload_snapshot":{"type":"object"}}},"WebhookEndpoint":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"url":{"type":"string","format":"uri"},"event_types":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"secret_last_four":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"WebhookEndpointCreate":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"event_types":{"type":"array","items":{"type":"string"}}},"required":["url","event_types"]},"WebhookEndpointWithSecret":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"secret_one_time":{"type":"string","description":"Use this to verify HMAC signatures. Only returned once."}}}]},"WebhookDelivery":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"webhook_endpoint_id":{"$ref":"#/components/schemas/UUID"},"event_type":{"type":"string"},"status":{"type":"string","enum":["pending","success","retrying","dead_letter"]},"attempt":{"type":"integer"},"last_attempted_at":{"type":"string","format":"date-time","nullable":true},"response_status_code":{"type":"integer","nullable":true},"response_body_excerpt":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"AuditLogEntry":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"occurred_at":{"type":"string","format":"date-time"},"actor_type":{"type":"string","enum":["user","system","service_account","webhook"]},"actor_id":{"$ref":"#/components/schemas/UUID"},"action":{"type":"string"},"resource_type":{"type":"string"},"resource_id":{"$ref":"#/components/schemas/UUID"},"before_state":{"type":"object","nullable":true},"after_state":{"type":"object","nullable":true},"client_ip":{"type":"string"},"request_id":{"type":"string"},"entry_hash":{"type":"string","description":"Phase 8: hash-chain entry"}}},"AuditLogList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogEntry"}},"next_cursor":{"type":"string","nullable":true}}},"PolicySnapshot":{"type":"object","properties":{"organization_id":{"$ref":"#/components/schemas/UUID"},"user_id":{"$ref":"#/components/schemas/UUID"},"provider_key_id":{"$ref":"#/components/schemas/UUID"},"provider":{"type":"string"},"provider_base_url":{"type":"string"},"provider_default_headers":{"type":"object"},"provider_secret_ciphertext":{"type":"string"},"secret_hash":{"type":"string","format":"byte"},"status":{"type":"string"},"expires_at":{"type":"string","format":"date-time","nullable":true},"limit_profile":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/UUID"},"rules":{"$ref":"#/components/schemas/LimitRules"}}},"allowed_origins":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"cost_center":{"type":"string"},"caching_enabled":{"type":"boolean"},"org_status":{"type":"string"},"org_default_origins":{"type":"array","items":{"type":"string"}},"org_default_ips":{"type":"array","items":{"type":"string"}}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"},"scope":{"type":"string"},"scope_id":{"type":"string"},"blocked_by":{"type":"string"},"reset_at":{"type":"string","format":"date-time"},"retry_after_seconds":{"type":"integer"}}}}}},"responses":{"Unauthorized":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Authenticated but lacks permission","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ValidationError":{"description":"Request body or params failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}