/auth/request-codeSend a 6-digit code and magic link (rate-limited).
- Body
- { email, turnstile_token, next? }
- Returns
- { ok: true }
REST endpoints, authentication and MCP tools. Connect your agent in the Agents hub.
All JSON. Times ISO-8601 UTC, days YYYY-MM-DD. Errors: { error: { code, message, details? } } with codes not_found, unauthorized, forbidden, validation, rate_limited, conflict, internal and the matching HTTP status. Paged lists accept limit/offset and return {items,total,limit,offset,has_more}; max 500 (keyword table 2000). Ads terms also include window.
Public and rate-limited: 5 codes per email and 20 per IP per 10 minutes.
/auth/request-codeSend a 6-digit code and magic link (rate-limited).
/auth/verifyExchange the code for a session cookie.
/auth/magic?token=&next=Magic link: sets the cookie and resumes a safe internal path, or the workspace/onboarding.
/auth/logoutClear the session cookie.
/auth/sessionCurrent session or 401.
/auth/accept-inviteAccept an invite after signing in.
Public OAuth 2.1 clients use S256 PKCE and resource=https://stora.rocks/mcp. The token and revocation endpoints accept form-urlencoded data and return OAuth protocol errors. Access expires in one hour; refresh rotates and expires in 30 days.
/.well-known/oauth-protected-resource/mcpMCP resource discovery.
/.well-known/oauth-authorization-serverIssuer, endpoints, scopes and public-client registration.
/oauth/registerRegister a client with HTTPS or native loopback redirects.
/oauth/authorizeSign in, select a workspace and consent. Requires response_type=code, client_id, redirect_uri, resource, S256 challenge; scope/state optional.
/oauth/tokenCode + verifier exchange or refresh-token rotation. client_id and resource required.
/oauth/revokeRevoke a connection using token and matching client_id.
/oauth/connectionsSigned-in browser: inspect and revoke your connections.
/api/v1/meUser, workspaces and the selected workspace.
/api/v1/accountsCreate a workspace; the creator is owner.
/api/v1/accounts/:idRename, timezone, ready-by hour of the daily scan (admin+).
/api/v1/accounts/:idDelete the workspace and all its data (owner, signed-in session). Cascades; audit-logged.
/api/v1/accounts/:id/switchSet the session's default workspace.
/api/v1/accounts/:id/membersMembers with roles.
/api/v1/accounts/:id/members/:user_idChange a role.
/api/v1/accounts/:id/members/:user_idRemove a member (owner only for owners).
/api/v1/accounts/:id/invitesInvite by email.
/api/v1/accounts/:id/invitesPending and accepted invites.
/api/v1/accounts/:id/invites/:invite_idRevoke an invite.
/api/v1/accounts/:id/api-keysKey metadata (never the key).
/api/v1/accounts/:id/api-keysCreate a key; admin requires write scope and a signed-in admin/owner. The full key is returned once.
/api/v1/accounts/:id/api-keys/:key_idRevoke a key.
/api/v1/accounts/:id/ads-connectionApple Ads connection status and last sync.
/api/v1/accounts/:id/ads-connectionSave credentials; the .p8 PEM is encrypted at rest.
/api/v1/accounts/:id/ads-connection/testRequest a token and list campaigns.
/api/v1/accounts/:id/ads-connectionDelete credentials.
/api/v1/accounts/:id/ads-syncStart an Apple Ads sync.
/api/v1/store/storefrontsEvery supported storefront (public, cached 1 day). Store codes in app and keyword writes must come from this list.
/api/v1/store/resolve?url=|apple_id=|google_package=&store=usResolve a store URL or ID to listing details and keyword suggestions.
/api/v1/store/hints?term=&store=usApp Store autocomplete.
/api/v1/appsApps with health, visibility and the top digest item.
/api/v1/appsAdd an app with keywords; queues a manual scan.
/api/v1/apps/:idFull app: settings, counts, health, Apple Ads state.
/api/v1/apps/:idUpdate identifiers, markets, depth, settings. Validates settings.profile with field-level errors; unknown store codes → 400 naming the code.
/api/v1/apps/:idDelete an app and its data (owner/admin).
/api/v1/apps/:id/scanQueue a manual scan. 409 if one ran within the hour.
/api/v1/apps/:id/runs?limit=30Scan runs with error text.
/api/v1/apps/:id/healthHealth row plus lane queue stats.
/api/v1/apps/:id/keywordsKeyword configuration with excluded_pairs and effective_pairs.
/api/v1/apps/:id/keywordsEnsure keyword scopes; existing markets are kept.
/api/v1/apps/:id/keywords/ensureEnsure 1–500 keyword scopes, returning added/effective pairs per item.
/api/v1/apps/:id/keywords/:kidActive, brand, note; replacing markets/platforms requires replace: true.
/api/v1/apps/:id/keywords/:kidDelete a keyword.
/api/v1/apps/:id/keywords/bulkBulk scope/flag changes, pair pause/resume, or delete. Preview with dry_run: true.
/api/v1/apps/:id/keywords/table?platform=&store=&status=&q=&sort=&order=The keyword table: one row per keyword, platform and market.
/api/v1/apps/:id/keywords/:kid/history?platform=&store=&days=90Ranks, popularity, paid, latest SERP and coverage.
/api/v1/apps/:id/keywords/export.csvCSV export of the keyword table.
/api/v1/apps/:id/digest?since=&day=&kinds=Digest items, newest first.
/api/v1/apps/:id/actions?state=open|waiting|done|dismissed|snoozed|resolved|allGrowth actions with evidence and gate status: open is ready (gate passed), waiting has not passed yet. The first page adds 30-day quality.
/api/v1/apps/:id/actions/:aidMark done, dismissed, snoozed or open, with an optional typed reason. Reopening an action whose gate has not passed returns it to waiting.
/api/v1/apps/:id/ideas?status=new|research|tracked|dismissed|all&intent=&dismiss_reason=Keyword ideas with intent, source, key and dismissal reason. New is the review queue; research keeps weaker candidates with evidence.admission.reasons.
/api/v1/apps/:id/ideas/:iid/trackEnsure the idea platform/store pair before marking tracked; returns the ensure result.
/api/v1/apps/:id/ideas/:iid/dismissDismiss an idea; default reason manual. no_demand and not_useful come back when the evidence changes; wrong_intent also labels it excluded.
/api/v1/apps/:id/intentsLabel 1–500 keywords or ideas; sessions default to manual, API keys to agent.
/api/v1/apps/:id/ideas/:iid/reopenReopen a dismissed idea with manual source; excluded becomes unknown.
/api/v1/apps/:id/competitors/:store_id/roleSet direct/adjacent/excluded role; null clears to discovered.
/api/v1/apps/:id/analytics?platform=&store=&days=28Visibility series, markets, movers, data quality. Without store (or store=all) every market is combined; without platform every platform.
/api/v1/apps/:id/competitors?platform=&days=28&role=Competitors by share of search, with role and reason.
/api/v1/apps/:id/competitors/:store_idCompetitor detail.
/api/v1/apps/:id/competitors/:store_id/discoverDiscover a competitor's keywords in the given markets: candidates from their localized listing, autocomplete, Apple Ads popularity and your tracked terms, verified with search-result scans. 409 within 24 h for the same competitor and market; cap × markets ≤ 1,000 jobs.
/api/v1/apps/:id/competitors/:store_id/keywords?platform=&store=&top=10|30&status=all|gap|trackedTheir verified keywords per market with their rank, your rank, tracked flag, popularity, sources and gap score, plus run progress.
/api/v1/apps/:id/competitors/gaps?platform=&store=&role=Terms where competitors reach the top 10 and you are unranked or not tracking the market, scored by popularity × 1/rank × role.
/api/v1/apps/:id/listing?store=Live listing, locales, draft, coverage and change log.
/api/v1/apps/:id/listing/draftSave the workspace draft for a market.
/api/v1/apps/:id/listing/changesLog a manual ledger entry.
/api/v1/apps/:id/experimentsExperiments. POST to create, PATCH /:eid to end.
/api/v1/apps/:id/ads/summarySpend, installs, CPI, waste, winners, negatives, target CPA, locales.
/api/v1/apps/:id/ads/terms?days=30&store=Paid search terms, aggregated.
/api/v1/apps/:id/ads/impression-share?store=Impression share per term.
/api/v1/apps/:id/ads/demand?store=Apple's curated genre term list.
/api/v1/portfolioBenchmark rows per app and platform.
/api/v1/changes?since=Workspace-wide digest across apps: what changed since a day.
/api/v1/openapi.jsonOpenAPI spec.
/api/healthService health and the deployed git SHA.
The same workspace data is available through the MCP server at /mcp. The Agents hub has client configuration and ready-to-run prompts.
get_connected_profileget_contextcreate_appupdate_appdelete_appresolve_storeget_storefrontsget_runsupdate_keyworddelete_keywordsave_listing_draftmark_draft_publishedlog_listing_changelist_experimentscreate_experimentupdate_experimentget_ads_impression_shareget_ads_demandget_portfoliotrigger_ads_syncget_ads_connectionget_keywordsget_analyticsget_ads_termsget_ads_campaignsget_ads_statelist_appsget_appget_keywords_tableget_keyword_historyadd_keywordsensure_keyword_scopesget_keyword_configbulk_keywordsdismiss_ideaget_digestget_actionsupdate_actionget_ideastrack_ideaget_listingget_healthtrigger_scanget_competitorsget_competitordiscover_competitor_keywordsget_competitor_keywordsget_competitor_gapslabel_intentsreopen_ideaset_competitor_roleget_ads_summaryget_changes_sincev1 Static copy of docs/API.md. Deterministic data only: no LLM runs inside Stora.