{"openapi":"3.0.3","info":{"title":"Cover My SaaS — Agent API","version":"1.0.0","description":"Machine-readable REST API for AI agents to autonomously manage subscription tracking for their human operators. All responses follow { success, data, error } shape.","contact":{"name":"Evan Brooks","url":"https://cover-my-saas.polsia.app"}},"servers":[{"url":"https://cover-my-saas.polsia.app","description":"Production"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Error":{"type":"object","properties":{"success":{"type":"boolean","example":false},"data":{"type":"null","example":null},"error":{"type":"string"}}},"Account":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"api_key":{"type":"string","description":"Use this key in X-API-Key header for all requests"},"account_id":{"type":"string"},"plan":{"type":"string","enum":["starter","pro"]},"rate_limit":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"error":{"type":"null"}}},"Subscription":{"type":"object","properties":{"id":{"type":"integer"},"platform":{"type":"string"},"platform_label":{"type":"string"},"workspace_name":{"type":"string","nullable":true},"monthly_cost":{"type":"number"},"seat_count":{"type":"integer"},"status":{"type":"string"},"last_active_at":{"type":"string","nullable":true,"format":"date-time"},"days_inactive":{"type":"integer","nullable":true},"usage_count_7d":{"type":"integer","nullable":true}}},"Usage":{"type":"object","properties":{"subscription_id":{"type":"integer"},"platform":{"type":"string"},"last_active":{"type":"string","nullable":true,"format":"date-time"},"days_inactive":{"type":"integer","nullable":true},"sessions_7d":{"type":"integer","nullable":true},"sessions_30d":{"type":"integer","nullable":true},"features_used":{"type":"string","nullable":true},"checked_at":{"type":"string","format":"date-time"}}},"Recommendation":{"type":"object","properties":{"subscription_id":{"type":"integer","nullable":true},"platform":{"type":"string"},"monthly_cost":{"type":"number"},"days_inactive":{"type":"integer"},"estimated_savings":{"type":"number"},"reason":{"type":"string"}}},"Plans":{"type":"object","properties":{"starter":{"type":"object","properties":{"price":{"type":"integer"},"currency":{"type":"string"},"billing":{"type":"string"},"platforms":{"type":"integer"},"features":{"type":"array","items":{"type":"string"}}}},"pro":{"type":"object","properties":{"price":{"type":"integer"},"currency":{"type":"string"},"billing":{"type":"string"},"platforms":{"type":"integer"},"features":{"type":"array","items":{"type":"string"}}}}}}}},"security":[{"ApiKeyAuth":[]}],"paths":{"/api/v1/auth/register":{"post":{"tags":["Auth"],"summary":"Register a new account and get an API key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"plan":{"type":"string","enum":["starter","pro"],"default":"starter"}}}}}},"responses":{"201":{"description":"Account created, returns api_key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Invalid email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Email already registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/auth/verify-key":{"get":{"tags":["Auth"],"summary":"Verify an API key and get account info","security":[],"responses":{"200":{"description":"Key valid","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"valid":{"type":"boolean"},"account_id":{"type":"string"},"email":{"type":"string"},"plan":{"type":"string"},"rate_limit_remaining":{"type":"integer"}}},"error":{"type":"null"}}}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/subscriptions":{"get":{"tags":["Subscriptions"],"summary":"List all tracked subscriptions","responses":{"200":{"description":"Subscriptions list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"subscriptions":{"type":"array","items":{"$ref":"#/components/schemas/Subscription"}},"summary":{"type":"object"}}},"error":{"type":"null"}}}}}}}},"post":{"tags":["Subscriptions"],"summary":"Add a subscription manually","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["platform"],"properties":{"platform":{"type":"string","description":"Platform key (e.g. slack, notion, figma)"},"workspace_name":{"type":"string"},"monthly_cost":{"type":"number"},"seat_count":{"type":"integer"},"url":{"type":"string"},"credentials":{"type":"object"}}}}}},"responses":{"201":{"description":"Subscription created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"subscription":{"$ref":"#/components/schemas/Subscription"}}},"error":{"type":"null"}}}}}},"400":{"description":"Invalid platform","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/subscriptions/scan":{"post":{"tags":["Subscriptions"],"summary":"Trigger Gmail receipt scan (async)","responses":{"202":{"description":"Scan queued","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"scan_id":{"type":"integer"},"status":{"type":"string"},"message":{"type":"string"}}},"error":{"type":"null"}}}}}}}}},"/api/v1/subscriptions/scan/{scan_id}":{"get":{"tags":["Subscriptions"],"summary":"Check scan status and results","parameters":[{"name":"scan_id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Scan job status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"null"}}}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/subscriptions/{id}":{"delete":{"tags":["Subscriptions"],"summary":"Remove a subscription","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"deleted":{"type":"boolean"},"id":{"type":"integer"}}},"error":{"type":"null"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/subscriptions/{id}/usage":{"get":{"tags":["Usage"],"summary":"Get latest usage snapshot","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Usage data","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Usage"},"error":{"type":"null"}}}}}}}}},"/api/v1/subscriptions/{id}/check":{"post":{"tags":["Usage"],"summary":"Trigger on-demand usage check (Kernel.sh + BrowserBase)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Check results","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"null"}}}}}}}}},"/api/v1/subscriptions/{id}/history":{"get":{"tags":["Usage"],"summary":"Usage history over time (last 30 checks)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Check history","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"null"}}}}}}}}},"/api/v1/vaults":{"get":{"tags":["Vault"],"summary":"List all vault connections","responses":{"200":{"description":"Vault list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"vaults":{"type":"array","items":{"type":"object"}}}},"error":{"type":"null"}}}}}}}}},"/api/v1/vaults/connect":{"post":{"tags":["Vault"],"summary":"Connect credential vault (1Password / Bitwarden)","description":"Connect a 1Password or Bitwarden vault for secure credential retrieval during activity checks. Agents never see raw passwords — the vault handles auth.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","credentials"],"properties":{"type":{"type":"string","enum":["1password","bitwarden"],"description":"Vault provider"},"credentials":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"Service account token or API key"},"server_url":{"type":"string","description":"Self-hosted server URL (Bitwarden only)"},"vault_id":{"type":"string","description":"1Password vault UUID to use"}}},"name":{"type":"string","description":"Human-readable vault name"}}}}}},"responses":{"200":{"description":"Vault connected","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"type":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"connected_at":{"type":"string","format":"date-time"},"message":{"type":"string"}}},"error":{"type":"null"}}}}}},"400":{"description":"Invalid vault type or missing credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/vaults/{id}/disconnect":{"delete":{"tags":["Vault"],"summary":"Disconnect a vault","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Vault disconnected","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"null"}}}}}},"404":{"description":"Vault not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/vaults/status":{"get":{"tags":["Vault"],"summary":"Get active vault connection status","responses":{"200":{"description":"Vault status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"connected":{"type":"boolean"},"id":{"type":"integer"},"type":{"type":"string"},"name":{"type":"string"},"last_synced":{"type":"string","format":"date-time"}}},"error":{"type":"null"}}}}}}}}},"/api/v1/digests/latest":{"get":{"tags":["Digests"],"summary":"Get latest activity data (real-time)","responses":{"200":{"description":"Digest data","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"null"}}}}}}}}},"/api/v1/digests/history":{"get":{"tags":["Digests"],"summary":"List previously sent digests","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"maximum":50}}],"responses":{"200":{"description":"Digest history","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"digests":{"type":"array","items":{"type":"object"}},"count":{"type":"integer"}}},"error":{"type":"null"}}}}}}}}},"/api/v1/digests/{id}":{"get":{"tags":["Digests"],"summary":"Get a specific sent digest by ID","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Digest","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"error":{"type":"null"}}}}}},"404":{"description":"Digest not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recommendations":{"get":{"tags":["Recommendations"],"summary":"Top 3 subscriptions to cut this week, sorted by waste","responses":{"200":{"description":"Recommendations","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"recommendations":{"type":"array","items":{"$ref":"#/components/schemas/Recommendation"}}}},"error":{"type":"null"}}}}}}}}},"/api/v1/plans":{"get":{"tags":["Plans"],"summary":"Public pricing — no auth required","security":[],"responses":{"200":{"description":"Plan pricing","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Plans"},"error":{"type":"null"}}}}}}}}}}}