{"openapi":"3.1.0","info":{"title":"Well Storage API","version":"1.0.0","description":"Central tenant-aware content and data provider for WebWise."},"servers":[{"url":"/"}],"components":{"securitySchemes":{"serviceBearer":{"type":"http","scheme":"bearer","bearerFormat":"opaque","description":"Internal WELL_STORAGE_SERVICE_TOKEN"},"storageEnvironment":{"type":"apiKey","in":"header","name":"X-Well-Storage-Environment","description":"Must match the deployment environment"}},"schemas":{},"parameters":{}},"paths":{"/v1/content/resolve":{"get":{"tags":["Content"],"summary":"Resolve a complete public render bundle","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"hostname","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"webIdentifier","in":"query"},{"schema":{"type":"string","minLength":1,"default":"/"},"required":false,"name":"path","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"locale","in":"query"},{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"pageSize","in":"query"}],"responses":{"200":{"description":"Tenant, route, content, layout, and collection data","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{}}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/content/tenant":{"get":{"tags":["Content"],"summary":"Fetch tenant identity, theme, and chrome","description":"Resolves without a path, so a consumer can render site furniture around a URL that resolved to nothing.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"hostname","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"webIdentifier","in":"query"}],"responses":{"200":{"description":"Tenant bundle","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{}}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/content/sitemap":{"get":{"tags":["Content"],"summary":"List every indexable URL for a tenant","description":"Unpaginated by design: a truncated sitemap tells crawlers the missing URLs do not exist.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"hostname","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"webIdentifier","in":"query"}],"responses":{"200":{"description":"Tenant bundle and its indexable URLs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"tenant":{"type":"object","additionalProperties":{}},"urls":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"lastmod":{"type":"string"}},"required":["path"]}}},"required":["tenant","urls"]}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/content/ads":{"get":{"tags":["Content"],"summary":"List direct-sold campaigns eligible for a slot","description":"Already filtered by date window, impression cap, and targeting, and sorted by priority. An unknown tenant yields an empty list rather than a 404.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"webIdentifier","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"slotId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"targeting","in":"query"}],"responses":{"200":{"description":"Eligible campaigns","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["campaigns"]}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/content/contact":{"post":{"tags":["Content"],"summary":"Store a contact submission and notify the tenant","description":"201 means the submission was stored. The result's `status` reports the notification email separately — a stored submission survives a failed send. CSRF and rate limiting belong to the calling edge.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webIdentifier":{"type":"string","minLength":1},"email":{"type":"string","format":"email"},"name":{"type":"string"},"phone":{"type":"string"},"subject":{"type":"string"},"message":{"type":"string"}},"required":["webIdentifier","email"]}}}},"responses":{"201":{"description":"Stored submission and notification outcome","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"uuid":{"type":"string"},"status":{"type":"string","enum":["sent","failed"]},"errorMessage":{"type":"string"}},"required":["uuid","status"]}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/content/newsletter":{"post":{"tags":["Content"],"summary":"Subscribe an address to a tenant's newsletter list","description":"404 when the tenant has no newsletter credentials — the feature is off for that tenant. There is no shared-key fallback.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webIdentifier":{"type":"string","minLength":1},"email":{"type":"string","format":"email"},"listId":{"anyOf":[{"type":"string","minLength":1},{"type":"number"}]},"fields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"doubleOptIn":{"type":"boolean"}},"required":["webIdentifier","email"]}}}},"responses":{"200":{"description":"Subscription result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"subscribed":{"type":"boolean"},"listId":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["subscribed","listId"]}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/resources/{resource}":{"get":{"tags":["Resources"],"summary":"List scoped records","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","enum":["users","agencies","agency-memberships","agency-invitations","clients","client-permissions","plans","subscriptions","payment-methods","invoices","pages","articles","article-layouts","categories","assets","media-folders","media-sync-states","dashboard-layouts","clients-layouts","contact-submissions","audit-logs","ad-campaigns","redirects","provider-secrets"]},"required":true,"name":"resource","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"agencyUuid","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"clientUuid","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"includeDeleted","in":"query"},{"schema":{"type":"string"},"required":true,"name":"x-well-storage-actor-uuid","in":"header"}],"responses":{"200":{"description":"Paginated records","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","minLength":1},"agencyUuid":{"type":"string","minLength":1},"clientUuid":{"type":"string","minLength":1}},"additionalProperties":{}}},"total":{"type":"number"}},"required":["items","total"]}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"tags":["Resources"],"summary":"Create a scoped record","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","enum":["users","agencies","agency-memberships","agency-invitations","clients","client-permissions","plans","subscriptions","payment-methods","invoices","pages","articles","article-layouts","categories","assets","media-folders","media-sync-states","dashboard-layouts","clients-layouts","contact-submissions","audit-logs","ad-campaigns","redirects","provider-secrets"]},"required":true,"name":"resource","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"agencyUuid","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"clientUuid","in":"query"},{"schema":{"type":"string"},"required":true,"name":"x-well-storage-actor-uuid","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"uuid":{"type":"string","minLength":1},"agencyUuid":{"type":"string","minLength":1},"clientUuid":{"type":"string","minLength":1}},"additionalProperties":{}}}}},"responses":{"201":{"description":"Created record","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"uuid":{"type":"string","minLength":1},"agencyUuid":{"type":"string","minLength":1},"clientUuid":{"type":"string","minLength":1}},"additionalProperties":{}}},"required":["data"]}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/v1/resources/{resource}/{uuid}":{"get":{"tags":["Resources"],"summary":"Read a scoped record","description":"Returns 404 both when the record does not exist and when it belongs to another tenant scope.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","enum":["users","agencies","agency-memberships","agency-invitations","clients","client-permissions","plans","subscriptions","payment-methods","invoices","pages","articles","article-layouts","categories","assets","media-folders","media-sync-states","dashboard-layouts","clients-layouts","contact-submissions","audit-logs","ad-campaigns","redirects","provider-secrets"]},"required":true,"name":"resource","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"uuid","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"agencyUuid","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"clientUuid","in":"query"},{"schema":{"type":"string"},"required":true,"name":"x-well-storage-actor-uuid","in":"header"}],"responses":{"200":{"description":"Resource operation result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"put":{"tags":["Resources"],"summary":"Replace a scoped record","description":"The payload becomes the record: stored fields it omits are cleared, except uuid, createdAt, and the tenant scope fields.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","enum":["users","agencies","agency-memberships","agency-invitations","clients","client-permissions","plans","subscriptions","payment-methods","invoices","pages","articles","article-layouts","categories","assets","media-folders","media-sync-states","dashboard-layouts","clients-layouts","contact-submissions","audit-logs","ad-campaigns","redirects","provider-secrets"]},"required":true,"name":"resource","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"uuid","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"agencyUuid","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"clientUuid","in":"query"},{"schema":{"type":"string"},"required":true,"name":"x-well-storage-actor-uuid","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"uuid":{"type":"string","minLength":1},"agencyUuid":{"type":"string","minLength":1},"clientUuid":{"type":"string","minLength":1}},"additionalProperties":{}}}}},"responses":{"200":{"description":"Resource operation result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"patch":{"tags":["Resources"],"summary":"Merge into a scoped record","description":"Only the fields present in the payload are written; everything else on the stored record is left untouched.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","enum":["users","agencies","agency-memberships","agency-invitations","clients","client-permissions","plans","subscriptions","payment-methods","invoices","pages","articles","article-layouts","categories","assets","media-folders","media-sync-states","dashboard-layouts","clients-layouts","contact-submissions","audit-logs","ad-campaigns","redirects","provider-secrets"]},"required":true,"name":"resource","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"uuid","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"agencyUuid","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"clientUuid","in":"query"},{"schema":{"type":"string"},"required":true,"name":"x-well-storage-actor-uuid","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"uuid":{"type":"string","minLength":1},"agencyUuid":{"type":"string","minLength":1},"clientUuid":{"type":"string","minLength":1}},"additionalProperties":{}}}}},"responses":{"200":{"description":"Resource operation result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"delete":{"tags":["Resources"],"summary":"Delete a scoped record","description":"Hard delete. Returns 404 when nothing matched in this scope.","security":[{"serviceBearer":[],"storageEnvironment":[]}],"parameters":[{"schema":{"type":"string","enum":["users","agencies","agency-memberships","agency-invitations","clients","client-permissions","plans","subscriptions","payment-methods","invoices","pages","articles","article-layouts","categories","assets","media-folders","media-sync-states","dashboard-layouts","clients-layouts","contact-submissions","audit-logs","ad-campaigns","redirects","provider-secrets"]},"required":true,"name":"resource","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"uuid","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"agencyUuid","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"clientUuid","in":"query"},{"schema":{"type":"string"},"required":true,"name":"x-well-storage-actor-uuid","in":"header"}],"responses":{"200":{"description":"Resource operation result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}}},"webhooks":{}}