{"openapi":"3.1.0","info":{"title":"Eformogi API","version":"31.0.0","description":"Personal Data Operating System — W3C Verifiable Credentials, vault management, form intelligence, and institutional data exchange.","contact":{"url":"https://eformogi.com"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://eformogi.com","description":"Production"}],"paths":{"/api/health":{"get":{"summary":"Health check","tags":["System"],"responses":{"200":{"description":"Server health status"}}}},"/api/status":{"get":{"summary":"Comprehensive service status","tags":["System"],"parameters":[{"name":"format","in":"query","schema":{"type":"string","enum":["badge"]}},{"name":"detail","in":"query","schema":{"type":"string","enum":["full"]}}],"responses":{"200":{"description":"Service health with per-dependency checks"},"503":{"description":"Service is down"}}}},"/api/schema":{"get":{"summary":"Vault schema discovery","tags":["Schema"],"parameters":[{"name":"format","in":"query","schema":{"type":"string","enum":["full","fields","openapi"]}},{"name":"category","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Vault field schema"}}}},"/api/jsonld-context":{"get":{"summary":"JSON-LD Context for Family Data Exchange Protocol","description":"Returns a JSON-LD @context document mapping Eformogi vault fields to linked data terms. Also available at /.well-known/context.jsonld.","tags":["Schema"],"responses":{"200":{"description":"JSON-LD context document","content":{"application/ld+json":{}}}}}},"/api/protocol-spec":{"get":{"summary":"FDEP Protocol Specification","description":"Returns the formal specification for the Family Data Exchange Protocol (FDEP). Defines data models, provenance, credential types, sharing, security, and compliance. Also available at /.well-known/fdep-spec.json.","tags":["Schema"],"responses":{"200":{"description":"FDEP specification document","content":{"application/json":{}}}}}},"/api/did":{"get":{"summary":"DID Document (W3C did:web)","tags":["Trust"],"responses":{"200":{"description":"W3C DID Document for did:web:eformogi.com","content":{"application/did+json":{}}}}}},"/api/revocation-list":{"get":{"summary":"Credential revocation list","tags":["Trust"],"parameters":[{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"type","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of revoked credential IDs"}}}},"/api/verify-credential":{"post":{"summary":"Verify a Verifiable Credential","tags":["Trust"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"credential":{"type":"object"}},"required":["credential"]}}}},"responses":{"200":{"description":"Verification result with proof, issuer, revocation, expiry checks"}}}},"/api/verify-receipt":{"get":{"summary":"Verify a receipt (tr_/cr_/ws_/wn_/wl_/att_, consent or audit id)","description":"The single verification front door for all Eformogi receipts.\nSingle-link verification is **free and keyless** — no account, no signup, ever\n(BRAND_THESIS rule 11). Paste any receipt id (`tr_`, `cr_`, `ws_`, `wn_`, `wl_`,\n`att_`, a consent receipt UUID, or an audit log id) and get back a verified,\nnon-PII metadata response.\n\n**Optional org attribution (V31 receiver billing):** send\n`Authorization: Bearer efg_org_…` to attribute the call to your org's plan.\nKeyed calls are counted toward your monthly verification quota\n(200/mo included on the $499/mo API plan; free orgs get 50/mo for evaluation).\nQuota state is returned in response headers:\n- `X-Verify-Quota-Plan` — your plan name (`free`, `api`, etc.)\n- `X-Verify-Quota-Limit` — monthly included verifications (omitted for unlimited plans)\n- `X-Verify-Quota-Used` — verifications used so far this calendar month\n\n**An invalid or unrecognised key never blocks a verify** — the endpoint falls back\nto the public (keyless) path so a misconfigured integration can never break a\nsingle-link verification. Paid plans (`api`, `professional`, `enterprise`) are\nnever blocked; only free-tier orgs over their evaluation allowance are gated\n(and only once `EFG_VERIFY_QUOTA_ENFORCE=true` is set — currently shadow mode).","tags":["Trust"],"security":[{},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"Receipt id to verify. Accepted formats: `tr_<12hex>` (transcript), `cr_<12hex>` (course receipt), `ws_<12hex>` (work sample), `wn_<12hex>` (Sunday Note), `wl_<12hex>` (wall), `att_<12hex>` (attestation), consent receipt UUID, or audit log UUID. Alias: `receipt_id` is accepted as a fallback query parameter."}],"responses":{"200":{"description":"Verification result. `verified: true` with non-PII metadata. Top-level fields vary by receipt kind but always include `verified` (boolean), `id` (string), `issued_by` (string), and `kind` (string). Actual values returned by the code: `family_transcript` (`tr_` ids), `course_receipt` (`cr_`), `work_sample` (`ws_`), `weekly_note` (`wn_`), `wall` (`wl_`), `attestation` (`att_`), `consent_receipt` (consent UUIDs), `event_receipt` (audit log UUIDs), `plan_receipt` (plan receipts)."},"402":{"description":"Free-tier org over monthly evaluation allowance (only when `EFG_VERIFY_QUOTA_ENFORCE=true`; paid plans never receive this). Response body fields: `error` (string), `plan` (string), `included` (number), `used` (number), `hint` (string), `upgrade_url` (string)."},"404":{"description":"Not a valid Eformogi receipt. Response shape is uniform (`verified: false`, `id`, `message`). For well-formed prefixes (`tr_`, `ws_`, `wn_`, `wl_`, `cr_`, `att_`) the message names the receipt family (e.g. \"No Eformogi work-sample receipt with this id.\"); unrecognised prefixes and UUIDs receive a generic fallback message. Existence is never confirmed — revoked, deleted, and never-issued ids all return 404."},"429":{"description":"Rate limited. Public path: 10 requests/min/IP."}}}},"/api/verify-consent":{"get":{"summary":"Verify a consent grant — check status, authorized fields, duration","description":"The core agent-facing endpoint. Returns consent status (active/expired/revoked), authorized field categories, purpose, time remaining, and verification provenance summary. Agents call this before reading profile data.","tags":["Agent Protocol"],"security":[{"orgApiKey":[]}],"parameters":[{"name":"consent_id","in":"query","required":true,"schema":{"type":"string","format":"uuid"},"description":"The consent grant ID to verify"}],"responses":{"200":{"description":"Consent verification result with status, scope, timestamps, and verification summary"},"401":{"description":"Invalid or missing API key"},"403":{"description":"Consent not active or not authorized"},"404":{"description":"Consent grant not found"}}}},"/api/profile-read":{"get":{"summary":"Read profile data authorized by a consent grant","description":"Returns profile data filtered to only the categories the consent grant authorizes AND the API key has scope for. Double enforcement: consent scope + API key scope. Proof-minimization at the API level.","tags":["Agent Protocol"],"security":[{"orgApiKey":[]}],"parameters":[{"name":"consent_id","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"categories","in":"query","schema":{"type":"string"},"description":"Comma-separated field categories to read. Defaults to all authorized categories."}],"responses":{"200":{"description":"Filtered profile data with only authorized categories"},"401":{"description":"Invalid or missing API key"},"403":{"description":"Requested categories exceed consent or API key scope"},"404":{"description":"Consent or profile not found"}}}},"/api/agent-action":{"get":{"summary":"Query the agent execution trace","description":"Returns a log of all agent data access events for the organization. Filterable by consent_id, action type, and time range. Constitutional Rule 6: receipts for everything.","tags":["Agent Protocol"],"security":[{"orgApiKey":[]}],"parameters":[{"name":"consent_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"action","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"page","in":"query","schema":{"type":"integer","default":1}}],"responses":{"200":{"description":"Paginated list of execution trace entries"}}},"post":{"summary":"Log a custom agent action","description":"Institutional systems log their own actions (EMR export, clinical note generation, forwarding) against a consent grant. Creates an auditable receipt.","tags":["Agent Protocol"],"security":[{"orgApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","description":"Action name (alphanumeric, dots, underscores)","example":"export.emr"},"consent_id":{"type":"string","format":"uuid"},"details":{"type":"object","description":"Structured details (max 10KB)"},"agent_id":{"type":"string","description":"Identifier for the agent performing the action"}},"required":["action"]}}}},"responses":{"201":{"description":"Action logged with trace ID"}}}},"/api/widget":{"get":{"summary":"Embeddable intake widget script","description":"Returns a JavaScript snippet that renders a consent intake button or form on any website. Orgs embed this on their site to let families share profiles directly.","tags":["Agent Protocol"],"parameters":[{"name":"slug","in":"query","required":true,"schema":{"type":"string"},"description":"Intake link slug"},{"name":"theme","in":"query","schema":{"type":"string","enum":["light","dark"],"default":"light"}},{"name":"position","in":"query","schema":{"type":"string","enum":["inline","floating"],"default":"inline"}},{"name":"text","in":"query","schema":{"type":"string"},"description":"Custom button text"}],"responses":{"200":{"description":"JavaScript widget code","content":{"application/javascript":{}}}}}},"/api/institutional/api-keys":{"get":{"summary":"List org API keys","description":"List all active API keys for the authenticated user's organization. Keys are masked.","tags":["Agent Protocol"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of API keys with scope and usage info"}}},"post":{"summary":"Create a scoped org API key","description":"Generate a new API key with optional field-category scoping. The key secret is only shown once.","tags":["Agent Protocol"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"allowed_categories":{"type":"array","items":{"type":"string"},"description":"Field categories this key can access. Omit for full access."},"expires_in_days":{"type":"integer","minimum":1,"maximum":365}}}}}},"responses":{"201":{"description":"API key created with secret (shown once)"}}},"delete":{"summary":"Revoke an org API key","tags":["Agent Protocol"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"API key revoked"}}}},"/api/get-share-link":{"get":{"summary":"Retrieve shared profile data","tags":["Sharing"],"parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Shared profile data"},"404":{"description":"Share link not found or expired"}}}},"/api/join-waitlist":{"post":{"summary":"Join the beta waitlist","tags":["Public"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"source":{"type":"string"}},"required":["email"]}}}},"responses":{"200":{"description":"Waitlist signup confirmed"}}}},"/api/api-inquiry":{"post":{"summary":"Submit institutional API access request","tags":["Public"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"organization":{"type":"string"},"useCase":{"type":"string","minLength":10},"message":{"type":"string"}},"required":["name","email","organization","useCase"]}}}},"responses":{"201":{"description":"Inquiry submitted for review"},"400":{"description":"Validation error"}}}},"/api/issue-credential":{"post":{"summary":"Issue a Verifiable Credential","tags":["Trust"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"categoryId":{"type":"string"},"fields":{"type":"object"},"provenance":{"type":"object"},"personName":{"type":"string"}},"required":["categoryId","fields"]}}}},"responses":{"200":{"description":"Signed W3C Verifiable Credential"},"401":{"description":"Authentication required"}}}},"/api/revoke-credential":{"post":{"summary":"Revoke a Verifiable Credential","tags":["Trust"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"credentialId":{"type":"string"},"reason":{"type":"string"}},"required":["credentialId"]}}}},"responses":{"200":{"description":"Credential revoked"},"403":{"description":"Not credential owner"},"409":{"description":"Already revoked"}}}},"/api/vault-sync":{"post":{"summary":"Sync vault data","tags":["Vault"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Vault data synced"}}}},"/api/extract-document":{"post":{"summary":"Extract data from uploaded document","tags":["Documents"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Extracted fields"}}}},"/api/match-fields":{"post":{"summary":"Match form fields to vault data","tags":["Forms"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Field matches"}}}},"/api/chat-assistant":{"post":{"summary":"Conversational AI assistant","tags":["AI"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Assistant response"}}}},"/api/family-invite":{"post":{"summary":"Send family sharing invite","tags":["Family"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Invite sent"}}}},"/api/consent-receipt":{"get":{"summary":"Get consent receipt","description":"Returns a machine-readable consent receipt (Kantara-inspired) for an institutional consent record.","tags":["Consent"],"parameters":[{"name":"consent_id","in":"query","required":true,"schema":{"type":"string"},"description":"The consent ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Consent receipt"},"404":{"description":"Consent not found"}}}},"/api/audit-log":{"get":{"summary":"Data access audit trail","description":"Returns the authenticated user's data access audit trail. Shows who accessed their shared data, consent events, and credential operations.","tags":["Consent"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100},"description":"Items per page"},{"name":"type","in":"query","schema":{"type":"string"},"description":"Filter by event type (e.g. share_link.accessed)"},{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category (e.g. data_access)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Paginated audit log events"},"401":{"description":"Authentication required"}}}},"/api/delete-account":{"post":{"summary":"Delete user account","description":"Permanently deletes the authenticated user's account and all associated data. Requires confirmation phrase. GDPR Art. 17 compliant.","tags":["Account"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["confirmation"],"properties":{"confirmation":{"type":"string","enum":["DELETE MY ACCOUNT"],"description":"Confirmation phrase"}}}}}},"responses":{"200":{"description":"Account permanently deleted"},"400":{"description":"Confirmation phrase required"},"401":{"description":"Authentication required"}}}},"/api/user-activity":{"get":{"summary":"Get user activity dashboard","description":"Returns comprehensive activity history including documents, form fills, AI usage, credentials, shares, audit events, and monthly trends.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Activity data including tier, documents, fills, ai, shares, credentials, auditEvents, monthlyTrend"},"401":{"description":"Authentication required"},"429":{"description":"Rate limited (30/min)"}}}},"/api/notifications":{"get":{"summary":"Get notifications","description":"Returns paginated list of user notifications with unread count. Supports filtering by read/unread status.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20},"description":"Max notifications to return"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Pagination offset"},{"name":"unread","in":"query","schema":{"type":"boolean"},"description":"Filter to unread only"}],"responses":{"200":{"description":"Notification list with total and unread counts"},"401":{"description":"Authentication required"},"429":{"description":"Rate limited (60/min)"}}},"patch":{"summary":"Mark notifications as read","description":"Mark specific notifications or all notifications as read.","tags":["Account"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"all":{"type":"boolean","description":"Mark all as read"},"ids":{"type":"array","items":{"type":"string"},"description":"Specific notification IDs to mark read"}}}}}},"responses":{"200":{"description":"Notifications marked as read"},"401":{"description":"Authentication required"}}}},"/api/data-export":{"get":{"summary":"Export all user data (GDPR Art. 20)","description":"Returns all personal data in JSON or CSV format. Includes vault data, documents, form fills, share links, credentials, consent receipts, audit log, notifications, AI usage, and family members.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"Export format"}],"responses":{"200":{"description":"Complete data export with Content-Disposition header for download"},"401":{"description":"Authentication required"},"429":{"description":"Rate limited (5/hour)"}}}},"/api/admin-users":{"get":{"summary":"Admin user management","description":"Paginated user list with vault/credential/share counts. Pass userId query param for single user detail. Requires admin secret.","tags":["Admin"],"parameters":[{"name":"x-admin-secret","in":"header","required":true,"schema":{"type":"string"}},{"name":"userId","in":"query","schema":{"type":"string"},"description":"Get single user detail"},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":50}},{"name":"search","in":"query","schema":{"type":"string"},"description":"Search by email or name"},{"name":"sort","in":"query","schema":{"type":"string","enum":["created_at","updated_at","email","last_sign_in_at"]}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"User list or single user detail"},"401":{"description":"Admin authorization required"},"429":{"description":"Rate limited (20/min)"}}}},"/api/admin-broadcast":{"get":{"summary":"List recent broadcasts","description":"Returns deduplicated list of recent system-wide broadcast notifications. Requires admin secret.","tags":["Admin"],"parameters":[{"name":"x-admin-secret","in":"header","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of recent broadcasts with recipient counts"},"401":{"description":"Admin authorization required"}}},"post":{"summary":"Send broadcast notification","description":"Sends a notification to all users. Batched in groups of 100. Requires admin secret.","tags":["Admin"],"parameters":[{"name":"x-admin-secret","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title"],"properties":{"title":{"type":"string","maxLength":200,"description":"Notification title"},"body":{"type":"string","maxLength":1000,"description":"Optional body text"},"type":{"type":"string","enum":["system","account_update"],"default":"system"}}}}}},"responses":{"200":{"description":"Broadcast sent with recipient count and broadcast ID"},"400":{"description":"Invalid input"},"401":{"description":"Admin authorization required"},"429":{"description":"Rate limited (10/min)"}}}},"/api/admin-feature-flags":{"get":{"summary":"List all feature flags","description":"Returns all feature flags with current values, defaults, override status, and descriptions. Requires admin secret.","tags":["Admin"],"parameters":[{"name":"x-admin-secret","in":"header","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of feature flags with enabled state and metadata"},"401":{"description":"Admin authorization required"},"429":{"description":"Rate limited (30/min)"}}},"patch":{"summary":"Toggle feature flags","description":"Update one or more feature flags. Values are persisted in the database and override defaults. Requires admin secret.","tags":["Admin"],"parameters":[{"name":"x-admin-secret","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["flags"],"properties":{"flags":{"type":"object","description":"Map of flag names to boolean values","example":{"FAMILY_VAULT_ADVANCED":true,"CHAT_ACTIONS":false}}}}}}},"responses":{"200":{"description":"Flags updated successfully"},"207":{"description":"Partial success — some flags updated, some failed"},"400":{"description":"Invalid input or unknown flag names"},"401":{"description":"Admin authorization required"},"429":{"description":"Rate limited (30/min)"}}}},"/api/admin-error-logs":{"get":{"summary":"View error logs","description":"Returns recent error reports from the error_logs table with filtering, pagination, and summary stats. Requires admin secret.","tags":["Admin"],"parameters":[{"name":"x-admin-secret","in":"header","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"type","in":"query","schema":{"type":"string","description":"Filter by error_type"}},{"name":"env","in":"query","schema":{"type":"string","description":"Filter by environment"}},{"name":"search","in":"query","schema":{"type":"string","description":"Search in error message"}},{"name":"hours","in":"query","schema":{"type":"integer","description":"Only errors from last N hours"}}],"responses":{"200":{"description":"Error logs with summary stats, pagination, and type breakdown"},"401":{"description":"Admin authorization required"},"429":{"description":"Rate limited (20/min)"}}}},"/api/security-events":{"get":{"summary":"Get security events","description":"Returns recent security-related events on the user's account: data access, share link views, credential events, consent changes, and account activity. All events are from the audit log.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":50},"description":"Number of events to return (max 50)"}],"responses":{"200":{"description":"Security events with summary stats and account info"},"401":{"description":"Authentication required"}}}},"/api/notification-preferences":{"get":{"summary":"Get notification preferences","description":"Returns the authenticated user's notification preferences with type descriptions.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Current preferences and available notification types"},"401":{"description":"Authentication required"}}},"patch":{"summary":"Update notification preferences","description":"Toggle notification types on/off. Merged with existing preferences.","tags":["Account"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["preferences"],"properties":{"preferences":{"type":"object","description":"Map of notification types to boolean values","example":{"share_viewed":true,"system":false}}}}}}},"responses":{"200":{"description":"Preferences updated"},"400":{"description":"Invalid type names or values"},"401":{"description":"Authentication required"}}}},"/api/feedback":{"post":{"summary":"Submit feedback","description":"Submit user feedback. Authentication optional — anonymous submissions accepted.","tags":["Account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","enum":["bug","feature","general","question"]},"message":{"type":"string","minLength":5,"maxLength":5000},"page":{"type":"string","description":"Page where feedback was submitted"},"metadata":{"type":"object","description":"Optional browser/device metadata"}}}}}},"responses":{"200":{"description":"Feedback submitted successfully"},"400":{"description":"Invalid type or message length"},"429":{"description":"Rate limited"}}},"get":{"summary":"List feedback (admin)","description":"Returns submitted feedback with filtering and summary stats. Admin secret required.","tags":["Admin"],"parameters":[{"name":"type","in":"query","schema":{"type":"string","enum":["bug","feature","general","question"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["new","reviewed","resolved","archived"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Feedback list with summary stats"},"401":{"description":"Admin authentication required"}}}},"/api/api-keys":{"get":{"summary":"List API keys","description":"Returns the authenticated user's active API keys with masked previews.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of active API keys"},"401":{"description":"Authentication required"}}},"post":{"summary":"Create API key","description":"Generate a new personal API key. The full key is only returned once at creation.","tags":["Account"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"description":"Friendly name for the key"},"expires_in_days":{"type":"integer","minimum":1,"maximum":365}}}}}},"responses":{"200":{"description":"API key created with secret (shown once)"},"400":{"description":"Maximum 5 active keys reached"},"401":{"description":"Authentication required"}}},"delete":{"summary":"Revoke API key","description":"Revoke an API key by ID. Cannot be undone.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"Key ID to revoke"}],"responses":{"200":{"description":"API key revoked"},"401":{"description":"Authentication required"},"404":{"description":"Key not found"}}}},"/api/sessions":{"get":{"summary":"List active sessions","description":"Returns active sessions for the authenticated user with device/browser info and IP.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of active sessions"},"401":{"description":"Authentication required"}}},"delete":{"summary":"Revoke a session","description":"Revoke an active session by ID, signing out that device remotely.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"Session event ID to revoke"}],"responses":{"200":{"description":"Session revoked"},"401":{"description":"Authentication required"},"404":{"description":"Session not found"}}}},"/api/data-retention":{"get":{"summary":"Get retention policies","description":"Returns the user's data retention policies for each category.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Current retention policies with category metadata"},"401":{"description":"Authentication required"}}},"patch":{"summary":"Update retention policies","description":"Update retention periods for specific data categories.","tags":["Account"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["policies"],"properties":{"policies":{"type":"object","description":"Map of category keys to retention_days values"}}}}}},"responses":{"200":{"description":"Policies updated"},"400":{"description":"Invalid retention period"},"401":{"description":"Authentication required"}}},"post":{"summary":"Preview or apply data retention","description":"Preview records eligible for deletion or apply retention policies. Use ?action=preview or ?action=apply.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"action","in":"query","required":true,"schema":{"type":"string","enum":["preview","apply"]}}],"responses":{"200":{"description":"Preview results or deletion confirmation"},"401":{"description":"Authentication required"}}}},"/api/trusted-devices":{"get":{"summary":"List trusted devices","description":"Returns all trusted (non-revoked) devices for the authenticated user, with current device detection.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Array of trusted devices with browser, OS, device type, and expiration info"},"401":{"description":"Authentication required"}}},"post":{"summary":"Trust current device","description":"Register the current browser/device as trusted. Maximum 10 trusted devices. Default expiration 90 days.","tags":["Account"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Custom device name"},"expires_in_days":{"type":"integer","minimum":1,"maximum":365,"description":"Days until trust expires (default 90)"}}}}}},"responses":{"200":{"description":"Device trusted successfully"},"400":{"description":"Maximum device limit reached"},"401":{"description":"Authentication required"}}},"delete":{"summary":"Remove trusted device","description":"Revoke trust for a specific device by ID.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"Device ID to remove"}],"responses":{"200":{"description":"Device trust revoked"},"401":{"description":"Authentication required"},"404":{"description":"Device not found"}}}},"/api/login-history":{"get":{"summary":"Get login history","description":"Returns paginated sign-in events with device info, IP, status, and authentication method.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Max results"},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Pagination offset"},{"name":"status","in":"query","schema":{"type":"string","enum":["all","success","failed"],"default":"all"},"description":"Filter by status"}],"responses":{"200":{"description":"Paginated login history with summary stats"},"401":{"description":"Authentication required"}}}},"/api/webhooks":{"get":{"summary":"List webhooks","description":"Returns all configured webhooks for the authenticated user, plus available event types.","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Array of webhooks with event subscriptions, status, and available events list"},"401":{"description":"Authentication required"}}},"post":{"summary":"Create webhook or send test ping","description":"Create a new webhook endpoint (max 5) or send a test ping with ?action=test. HTTPS URLs only. Returns signing secret on creation.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"action","in":"query","schema":{"type":"string","enum":["test"]},"description":"Set to \"test\" to send a test ping instead of creating"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Webhook name"},"url":{"type":"string","format":"uri","description":"HTTPS endpoint URL"},"events":{"type":"array","items":{"type":"string"},"description":"Event types to subscribe to"},"id":{"type":"string","description":"Webhook ID (for test ping only)"}}}}}},"responses":{"200":{"description":"Webhook created with signing secret, or test ping result"},"400":{"description":"Invalid URL, missing events, or limit reached"},"401":{"description":"Authentication required"}}},"delete":{"summary":"Delete webhook","description":"Permanently delete a webhook endpoint.","tags":["Account"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"Webhook ID to delete"}],"responses":{"200":{"description":"Webhook deleted"},"401":{"description":"Authentication required"},"404":{"description":"Webhook not found"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Supabase JWT access token"},"orgApiKey":{"type":"apiKey","in":"header","name":"Authorization","description":"Institutional org API key. Use \"Bearer efg_org_...\" or \"Api-Key efg_org_...\" header. Keys are scoped to specific data categories."}}},"tags":[{"name":"System","description":"Health and status monitoring"},{"name":"Trust","description":"W3C Verifiable Credentials and DID"},{"name":"Schema","description":"Vault schema and protocol discovery"},{"name":"Sharing","description":"Profile sharing"},{"name":"Public","description":"Unauthenticated endpoints"},{"name":"Vault","description":"Personal data vault operations"},{"name":"Documents","description":"Document processing"},{"name":"Forms","description":"Form intelligence"},{"name":"AI","description":"AI assistant"},{"name":"Family","description":"Family sharing"},{"name":"Consent","description":"Institutional consent and receipts"},{"name":"Account","description":"User account management"},{"name":"Admin","description":"Admin dashboard and user management"},{"name":"Agent Protocol","description":"Machine-readable consent verification, scoped data access, and execution tracing for AI agents and integrations"}]}