{"openapi":"3.0.0","info":{"title":"SpreadJam API","version":"1.0.0"},"tags":[{"name":"Meta","description":"Identity and metadata about the authenticated key."},{"name":"Keywords","description":"Keyword and topic visibility rankings."},{"name":"API keys","description":"Manage the workspace's API keys."},{"name":"Analytics","description":"AI-visibility analytics for the workspace."},{"name":"Brand","description":"The workspace's brand profile and competitors."},{"name":"Prompts","description":"Tracked GEO prompts and their cap state."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A workspace API key issued in Settings → Developer, sent as `Bearer sk_…`."}},"schemas":{"Me":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","example":"user_123"},"name":{"type":"string","nullable":true,"description":"The key owner's display name; null when absent."},"email":{"type":"string","nullable":true,"description":"The key owner's email; null when absent."}},"required":["id","name","email"]},"workspaceId":{"type":"string","example":"ws_123"},"environment":{"type":"string","enum":["test","live"],"example":"test"}},"required":["user","workspaceId","environment"]},"AnalyticsOverview":{"type":"object","description":"Headline visibility metrics, per-platform breakdown, citation leaderboard, and topic rankings."},"PromptAnalytics":{"type":"object","description":"Tracked prompts with per-platform state and KPI/trend metrics, after the requested filters."},"MetricRows":{"type":"object","description":"The flattened, chart-ready rows for one metric family."},"BrandProfile":{"type":"object","properties":{"version":{"type":"integer","example":3},"positioning":{"type":"string","nullable":true},"audience":{"type":"string","nullable":true},"productDescription":{"type":"string","nullable":true},"tone":{"type":"string","nullable":true},"contentStyle":{"type":"string","nullable":true},"competitors":{"type":"array","items":{"type":"string"}},"excludedTopics":{"type":"array","items":{"type":"string"}},"competitorsPinnedAt":{"type":"string","nullable":true,"description":"ISO-8601 UTC when the competitor list was pinned; null when not pinned."}},"required":["version","positioning","audience","productDescription","tone","contentStyle","competitors","excludedTopics","competitorsPinnedAt"]},"SaveBrandPositioningResult":{"type":"object","properties":{"version":{"type":"integer","example":4},"superseded":{"type":"boolean","description":"Whether a prior active version was superseded."}},"required":["version","superseded"]},"SaveBrandPositioning":{"type":"object","properties":{"positioning":{"type":"string","minLength":3,"maxLength":2000,"description":"The brand positioning statement."},"audience":{"type":"string","nullable":true},"productDescription":{"type":"string","nullable":true},"tone":{"type":"string","nullable":true},"competitors":{"type":"array","items":{"type":"string"}},"excludedTopics":{"type":"array","items":{"type":"string"}},"rawIntent":{"type":"string","description":"Verbatim free-text the author typed."}},"required":["positioning"]},"CompetitorsResult":{"type":"object","properties":{"count":{"type":"integer","example":5}},"required":["count"]},"PinCompetitors":{"type":"object","properties":{"competitors":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":64,"description":"The competitor list to pin (1 to 64 names)."}},"required":["competitors"]},"Recalibration":{"type":"object","properties":{"runId":{"type":"string"},"dispatch":{"type":"object","properties":{"status":{"type":"string"},"outboxId":{"type":"string","nullable":true}},"required":["status","outboxId"]}},"required":["runId","dispatch"]},"Prompts":{"type":"object","properties":{"tracked":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"topic":{"type":"string","nullable":true},"status":{"type":"string"},"createdBy":{"type":"string"},"pausedReason":{"type":"string","nullable":true},"archivedBy":{"type":"string","nullable":true},"archivedReason":{"type":"string","nullable":true},"hasObservations":{"type":"boolean"},"updatedAt":{"type":"string","description":"ISO-8601 UTC timestamp."}},"required":["id","text","topic","status","createdBy","pausedReason","archivedBy","archivedReason","hasObservations","updatedAt"]}},"archived":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"topic":{"type":"string","nullable":true},"status":{"type":"string"},"createdBy":{"type":"string"},"pausedReason":{"type":"string","nullable":true},"archivedBy":{"type":"string","nullable":true},"archivedReason":{"type":"string","nullable":true},"hasObservations":{"type":"boolean"},"updatedAt":{"type":"string","description":"ISO-8601 UTC timestamp."}},"required":["id","text","topic","status","createdBy","pausedReason","archivedBy","archivedReason","hasObservations","updatedAt"]}}},"required":["tracked","archived"]},"PromptCap":{"type":"object","properties":{"activeCount":{"type":"integer","example":12},"cap":{"type":"integer","description":"The effective prompt cap; -1 means unlimited.","example":50}},"required":["activeCount","cap"]},"AddPromptResult":{"type":"object","properties":{"promptId":{"type":"string"},"activeCount":{"type":"integer","example":13},"cap":{"type":"integer","description":"The effective prompt cap; -1 means unlimited.","example":50}},"required":["promptId","activeCount","cap"]},"AddPrompt":{"type":"object","properties":{"text":{"type":"string","minLength":3,"maxLength":500,"description":"Prompt wording (3 to 500 characters)."},"persona":{"type":"string","enum":["discoverer","buyer","evaluator","competitor","branded","control"],"description":"Buyer-journey persona; defaults to discoverer."},"topic":{"type":"string","nullable":true,"description":"Optional topic/theme label."},"intent":{"type":"string","nullable":true,"description":"Optional buyer intent."}},"required":["text"]},"EditPromptResult":{"type":"object","properties":{"promptId":{"type":"string"},"changed":{"type":"boolean","description":"Whether the wording actually changed."},"wordingChange":{"type":"string","enum":["minor","major","none"]}},"required":["promptId","changed","wordingChange"]},"RewordPrompt":{"type":"object","properties":{"text":{"type":"string","minLength":3,"maxLength":500,"description":"The new prompt wording (3 to 500 characters)."}},"required":["text"]},"BulkEditPromptsResult":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"changed":{"type":"boolean","description":"Whether the wording actually changed."},"wordingChange":{"type":"string","enum":["minor","major","none"]}},"required":["id","changed","wordingChange"]}}},"required":["results"]},"BulkEditPrompts":{"type":"object","properties":{"prompts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"description":"The prompt to reword.","example":"prompt-123"},"text":{"type":"string","minLength":3,"maxLength":500,"description":"The new wording (3 to 500 characters)."}},"required":["id","text"]},"minItems":1,"maxItems":100,"description":"The prompts to reword, by id (1 to 100)."}},"required":["prompts"]},"BulkInsertPromptsResult":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"promptId":{"type":"string"},"created":{"type":"boolean","description":"true if newly tracked, false if an existing prompt was reused."}},"required":["promptId","created"]}},"activeCount":{"type":"integer","example":14},"cap":{"type":"integer","description":"The effective prompt cap; -1 means unlimited.","example":50}},"required":["results","activeCount","cap"]},"BulkInsertPrompts":{"type":"object","properties":{"prompts":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string","minLength":3,"maxLength":500,"description":"Prompt wording (3 to 500 characters)."},"persona":{"type":"string","enum":["discoverer","buyer","evaluator","competitor","branded","control"],"description":"Buyer-journey persona; defaults to discoverer."},"topic":{"type":"string","nullable":true,"description":"Optional topic/theme label."},"intent":{"type":"string","nullable":true,"description":"Optional buyer intent."}},"required":["text"]},"minItems":1,"maxItems":100,"description":"The prompts to track (1 to 100). A text matching an existing tracked prompt reuses it."}},"required":["prompts"]},"PausePromptResult":{"type":"object","properties":{"promptId":{"type":"string"},"status":{"type":"string"}},"required":["promptId","status"]},"PausePrompt":{"type":"object","properties":{"paused":{"type":"boolean","description":"true to pause tracking, false to resume."},"reason":{"type":"string","nullable":true,"description":"Optional note on why the prompt was paused."}},"required":["paused"]},"RemovePromptResult":{"type":"object","properties":{"promptId":{"type":"string"}},"required":["promptId"]},"ReplacePromptResult":{"type":"object","properties":{"promptId":{"type":"string"},"archivedPromptId":{"type":"string"}},"required":["promptId","archivedPromptId"]},"ApiKeyList":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"environment":{"type":"string","enum":["test","live"]},"keyPrefix":{"type":"string"},"createdAt":{"type":"string","description":"ISO-8601 UTC timestamp."},"lastUsedAt":{"type":"string","nullable":true},"revokedAt":{"type":"string","nullable":true}},"required":["id","name","environment","keyPrefix","createdAt","lastUsedAt","revokedAt"]}}},"required":["keys"]},"IssuedApiKey":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string","description":"The raw secret key. Shown once, at creation; store it now."},"keyPrefix":{"type":"string"}},"required":["id","key","keyPrefix"]},"IssueApiKey":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"A label so you can find the key later."},"environment":{"type":"string","enum":["test"],"default":"test","description":"The key environment. Only `test` is issued today; live keys require a paid plan."}},"required":["name"]}},"parameters":{}},"paths":{"/v1/me":{"get":{"tags":["Meta"],"summary":"The authenticated key's workspace","description":"Returns the workspace and environment the bearer key is scoped to.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The authenticated workspace context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}}}}},"/v1/analytics/overview":{"get":{"tags":["Analytics"],"summary":"AI-visibility overview","description":"Headline metrics, per-platform breakdown, citation leaderboard, and topic rankings.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","default":30,"description":"The analytics window in days: 7, 30, or 90.","example":30},"required":false,"description":"The analytics window in days: 7, 30, or 90.","name":"rangeDays","in":"query"}],"responses":{"200":{"description":"The visibility overview.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsOverview"}}}}}}},"/v1/analytics/prompts":{"get":{"tags":["Analytics"],"summary":"Per-prompt analytics","description":"Tracked prompts with per-platform state and KPI/trend metrics, one page at a time.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","default":30,"description":"The analytics window in days: 7, 30, or 90.","example":30},"required":false,"description":"The analytics window in days: 7, 30, or 90.","name":"rangeDays","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Maximum number of items to return (1–100).","example":20},"required":false,"description":"Maximum number of items to return (1–100).","name":"limit","in":"query"},{"schema":{"anyOf":[{"type":"string","enum":["draft","active","paused","archived","regenerating","pending_baseline","stale","failed_all_platforms"]},{"type":"array","items":{"type":"string","enum":["draft","active","paused","archived","regenerating","pending_baseline","stale","failed_all_platforms"]}},{"type":"string"}],"description":"Filter by prompt status."},"required":false,"description":"Filter by prompt status.","name":"status","in":"query"},{"schema":{"anyOf":[{"type":"string","enum":["discoverer","buyer","evaluator","custom"]},{"type":"array","items":{"type":"string","enum":["discoverer","buyer","evaluator","custom"]}},{"type":"string"}],"description":"Filter by persona."},"required":false,"description":"Filter by persona.","name":"persona","in":"query"},{"schema":{"anyOf":[{"type":"string","enum":["informational","commercial","comparison","transactional","support"]},{"type":"array","items":{"type":"string","enum":["informational","commercial","comparison","transactional","support"]}},{"type":"string"}],"description":"Filter by intent."},"required":false,"description":"Filter by intent.","name":"intent","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Filter by topic label(s)."},"required":false,"description":"Filter by topic label(s).","name":"topic","in":"query"},{"schema":{"type":"string","description":"Free-text search over prompt text and topic."},"required":false,"description":"Free-text search over prompt text and topic.","name":"query","in":"query"}],"responses":{"200":{"description":"The per-prompt analytics page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptAnalytics"}}}}}}},"/v1/analytics/metrics":{"get":{"tags":["Analytics"],"summary":"Flattened metric rows","description":"Chart-ready rows for one of visibility, competitors, citations, platforms, or topics.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["visibility","competitors","citations","platforms","topics"],"description":"The metric family to flatten into chart-ready rows.","example":"visibility"},"required":true,"description":"The metric family to flatten into chart-ready rows.","name":"metric","in":"query"},{"schema":{"type":"number","default":30,"description":"The analytics window in days: 7, 30, or 90.","example":30},"required":false,"description":"The analytics window in days: 7, 30, or 90.","name":"rangeDays","in":"query"}],"responses":{"200":{"description":"The flattened metric rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricRows"}}}}}}},"/v1/keywords":{"get":{"tags":["Keywords"],"summary":"Keyword and topic visibility","description":"Per-topic visibility rankings (the `topics` analytics metric under its own name).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","default":30,"description":"The analytics window in days: 7, 30, or 90.","example":30},"required":false,"description":"The analytics window in days: 7, 30, or 90.","name":"rangeDays","in":"query"}],"responses":{"200":{"description":"The topic visibility rows.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MetricRows"},{"nullable":true}]}}}}}}},"/v1/brand":{"get":{"tags":["Brand"],"summary":"The active brand profile","description":"Positioning, audience, product, tone, competitors, excluded topics, and pin state.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The active brand profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandProfile"}}}}}},"patch":{"tags":["Brand"],"summary":"Save brand positioning","description":"Author a new positioning version. Requires a paid plan.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveBrandPositioning"}}}},"responses":{"200":{"description":"The new active version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveBrandPositioningResult"}}}}}}},"/v1/brand/competitors":{"put":{"tags":["Brand"],"summary":"Pin the competitor list","description":"Pin and lock the competitor list on the active profile. Requires a paid plan.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinCompetitors"}}}},"responses":{"200":{"description":"The pinned competitor count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompetitorsResult"}}}}}},"delete":{"tags":["Brand"],"summary":"Clear the competitor pin","description":"Clear the competitor pin on the active profile, leaving the list untouched. Requires a paid plan.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The current competitor count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompetitorsResult"}}}}}}},"/v1/brand/recalibrations":{"post":{"tags":["Brand"],"summary":"Start a recalibration","description":"Rebuild the GEO system layer toward the active authored positioning.","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"The recalibration run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recalibration"}}}}}}},"/v1/prompts":{"get":{"tags":["Prompts"],"summary":"Tracked and archived prompts","description":"The editable prompts for the workspace's active GEO project.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The editable prompts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Prompts"}}}}}},"post":{"tags":["Prompts"],"summary":"Track a new prompt","description":"Add a tracked prompt to the workspace's active GEO project. Requires a paid plan.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPrompt"}}}},"responses":{"201":{"description":"The tracked prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPromptResult"}}}}}},"put":{"tags":["Prompts"],"summary":"Reword many prompts at once","description":"Reword up to 100 tracked prompts by id in one atomic operation, keeping each prompt's measurement history. Any item that is missing, not editable, or has invalid text fails the whole batch. Requires a paid plan.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEditPrompts"}}}},"responses":{"200":{"description":"The per-prompt reword results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEditPromptsResult"}}}}}}},"/v1/prompts/cap":{"get":{"tags":["Prompts"],"summary":"Prompt cap state","description":"How many prompt slots are occupied and the effective cap.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The prompt cap state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptCap"}}}}}}},"/v1/prompts/{promptId}":{"patch":{"tags":["Prompts"],"summary":"Reword a prompt in place","description":"Reword a tracked prompt, keeping its measurement history. Requires a paid plan.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prompt-123"},"required":true,"name":"promptId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RewordPrompt"}}}},"responses":{"200":{"description":"The reworded prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditPromptResult"}}}}}},"delete":{"tags":["Prompts"],"summary":"Stop tracking a prompt","description":"Soft-archive a tracked prompt (measurement history is retained). Requires a paid plan.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prompt-123"},"required":true,"name":"promptId","in":"path"}],"responses":{"200":{"description":"The archived prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePromptResult"}}}}}}},"/v1/prompts/bulk":{"post":{"tags":["Prompts"],"summary":"Track many prompts at once","description":"Track up to 100 prompts in one atomic operation. An incoming text matching an existing tracked prompt reuses that prompt rather than duplicating it. The prompt cap is checked once over the whole batch; a batch that would exceed it is rejected and nothing is tracked. Requires a paid plan.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkInsertPrompts"}}}},"responses":{"201":{"description":"The per-prompt tracking results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkInsertPromptsResult"}}}}}}},"/v1/prompts/{promptId}/pause":{"post":{"tags":["Prompts"],"summary":"Pause or resume a prompt","description":"Toggle whether a tracked prompt is measured. Requires a paid plan.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prompt-123"},"required":true,"name":"promptId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PausePrompt"}}}},"responses":{"200":{"description":"The prompt with its new status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PausePromptResult"}}}}}}},"/v1/prompts/{promptId}/replacements":{"post":{"tags":["Prompts"],"summary":"Replace a prompt, resetting history","description":"Reword a tracked prompt and reset its measurement history (archives the old prompt, tracks a new one in its place). Requires a paid plan.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"example":"prompt-123"},"required":true,"name":"promptId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RewordPrompt"}}}},"responses":{"201":{"description":"The replacement prompt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplacePromptResult"}}}}}}},"/v1/api-keys":{"get":{"tags":["API keys"],"summary":"List API keys","description":"The workspace's API keys (never the raw secret).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The workspace's keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"}}}}}},"post":{"tags":["API keys"],"summary":"Create an API key","description":"Create a key for the workspace. The raw secret is returned once, here, and never again.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueApiKey"}}}},"responses":{"201":{"description":"The created key, including the raw secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedApiKey"}}}}}}},"/v1/api-keys/{keyId}":{"delete":{"tags":["API keys"],"summary":"Revoke an API key","description":"Revoke a key in the workspace. Revoking is a soft delete and is idempotent.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"keyId","in":"path"}],"responses":{"204":{"description":"The key was revoked."}}}}}}