{"openapi":"3.1.0","info":{"title":"ListShack Agent API","version":"2.0.0","description":"The REST API behind the ListShack MCP server. Most agents should connect to the MCP server at `https://dev.listshack.io/api/mcp` instead; every MCP tool maps to one operation below.\n\n## Authentication\n\nOAuth 2.1 Authorization Code with PKCE. The person connecting the agent signs in to ListShack, chooses an account and approves ListShack capabilities; send the access token as `Authorization: Bearer <access_token>`. There are no static API keys.\n\n## Typical flow\n\n1. `GET /api/v1/access-status` — plan, capabilities and remaining free calls.\n2. `GET /api/v1/databases` and `/api/v1/databases/{databaseId}` — what can be searched.\n3. `POST /api/v1/search-field-values` and `/api/v1/count-records` — explore values and counts.\n4. `POST /api/v1/searches`, then quote and purchase — the person who connected the agent confirms every purchase.\n\nRetry a failed metered or purchase request with its original `X-ListShack-Request-Id`; identical retries are never charged twice.","contact":{"name":"ListShack","url":"https://listshack.com"}},"servers":[{"url":"https://dev.listshack.io"}],"security":[{"ListShackOAuth":[]}],"tags":[{"name":"Databases","description":"Databases an agent may search and their searchable fields. Catalog reads are free."},{"name":"Access","description":"Plan, capabilities, free allowance and credits for the account the agent was connected to."},{"name":"Searches","description":"Field values, counts, owned searches and masked previews. Counts and field-value lookups use the free allowance on free plans."},{"name":"Purchases","description":"Quote and buy a list from an owned search. Every purchase is confirmed by the person who connected the agent."}],"paths":{"/api/v1/databases":{"get":{"tags":["Databases"],"summary":"List Databases","description":"**List searchable ListShack databases.**\n\nReturns stable database IDs and descriptive metadata. It does not expose physical search index names or record data. Catalog reads are free and do not consume the monthly allowance.\n\n**Required ListShack capabilities:** `catalog.read`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["databases"],"properties":{"databases":{"type":"array","items":{"type":"object","required":["id","searchable","datasetVersion","type","title","description","releasedDate","geographyFields","filterCategories","searchableFields","outputFields","useCases","creditMultiplier","appliedPolicySummaries"],"properties":{"id":{"type":"string","description":"Stable ListShack dictionary identifier; physical search index names are not exposed."},"searchable":{"type":"boolean","description":"Whether this dataset is enabled for versioned search requests."},"datasetVersion":{"type":["string","null"],"description":"Dataset release or validated mapping-contract version."},"type":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"releasedDate":{"type":["string","null"],"format":"date"},"geographyFields":{"type":"array","items":{"type":"string"}},"filterCategories":{"type":"array","items":{"type":"string"}},"searchableFields":{"type":"array","items":{"type":"object","required":["name","type","operators"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean","date"]},"operators":{"type":"array","items":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","in","like","exists","missing"]}}}}},"outputFields":{"type":"array","items":{"type":"string"}},"useCases":{"type":"array","items":{"type":"object","required":["id","description"],"properties":{"id":{"type":"string"},"description":{"type":"string"}}}},"creditMultiplier":{"type":["number","null"],"minimum":0},"appliedPolicySummaries":{"type":"array","items":{"type":"object","required":["id","mandatory","description"],"properties":{"id":{"type":"string"},"mandatory":{"type":"boolean"},"description":{"type":"string"}}}}}}}}}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The OAuth grant does not include catalog.read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Agent traffic admission is temporarily unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["catalog.read"]}},"/api/v1/databases/{databaseId}":{"get":{"tags":["Databases"],"summary":"Describe Database","description":"**Describe a searchable ListShack database.**\n\nReturns stable database metadata and the geographic/filter categories available for that dataset. Catalog reads are free and do not consume the monthly allowance.\n\n**Required ListShack capabilities:** `catalog.read`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["id","searchable","datasetVersion","type","title","description","releasedDate","geographyFields","filterCategories","searchableFields","outputFields","useCases","creditMultiplier","appliedPolicySummaries"],"properties":{"id":{"type":"string","description":"Stable ListShack dictionary identifier; physical search index names are not exposed."},"searchable":{"type":"boolean","description":"Whether this dataset is enabled for versioned search requests."},"datasetVersion":{"type":["string","null"],"description":"Dataset release or validated mapping-contract version."},"type":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"releasedDate":{"type":["string","null"],"format":"date"},"geographyFields":{"type":"array","items":{"type":"string"}},"filterCategories":{"type":"array","items":{"type":"string"}},"searchableFields":{"type":"array","items":{"type":"object","required":["name","type","operators"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean","date"]},"operators":{"type":"array","items":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","in","like","exists","missing"]}}}}},"outputFields":{"type":"array","items":{"type":"string"}},"useCases":{"type":"array","items":{"type":"object","required":["id","description"],"properties":{"id":{"type":"string"},"description":{"type":"string"}}}},"creditMultiplier":{"type":["number","null"],"minimum":0},"appliedPolicySummaries":{"type":"array","items":{"type":"object","required":["id","mandatory","description"],"properties":{"id":{"type":"string"},"mandatory":{"type":"boolean"},"description":{"type":"string"}}}}}}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The OAuth grant does not include catalog.read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Agent traffic admission is temporarily unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["catalog.read"],"parameters":[{"name":"databaseId","in":"path","required":true,"schema":{"type":"string"},"description":"Stable ListShack dictionary identifier."}]}},"/api/v1/access-status":{"get":{"tags":["Access"],"summary":"Get Access Status","description":"**Get the current delegated API access and usage status.**\n\nReturns current server-verified OAuth identity scopes, ListShack grant capabilities, account tier, free usage and eligible paid credit availability. First-party browser sessions do not receive the promotional agent allowance.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["tier","accountRole","selectedAccount","oauthIdentityScopes","capabilities","planRestrictions","freeUsage","creditAvailability","upgradeUrl"],"properties":{"tier":{"type":"string"},"accountRole":{"type":"string"},"selectedAccount":{"type":"object","required":["accountUid","role"],"properties":{"accountUid":{"type":"string"},"role":{"type":"string"}}},"oauthIdentityScopes":{"type":"array","items":{"type":"string"}},"capabilities":{"type":"array","items":{"type":"string"}},"planRestrictions":{"type":"object","required":["perDownloadLimit","searchSuppressions","verifiedMembership"],"properties":{"perDownloadLimit":{"type":"integer","minimum":0},"searchSuppressions":{"type":"boolean"},"verifiedMembership":{"type":"boolean"}}},"freeUsage":{"type":"object","required":["policyVersion","period","limit","used","remaining","resetsAt"],"additionalProperties":false,"properties":{"policyVersion":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._-]+$"},"period":{"type":"string","enum":["calendar_month_utc"]},"unlimited":{"type":"boolean"},"limit":{"type":["integer","null"],"minimum":1,"maximum":9007199254740991},"used":{"type":"integer","minimum":0,"maximum":9007199254740991},"remaining":{"type":["integer","null"],"minimum":0,"maximum":9007199254740991},"resetsAt":{"type":"string","maxLength":32,"format":"date-time","pattern":"^\\d{4}-\\d{2}-01T00:00:00(?:\\.000)?Z$"}}},"creditAvailability":{"anyOf":[{"type":"null"},{"type":"object","required":["monthly","addOn","perDownloadLimit"],"properties":{"monthly":{"type":"integer","minimum":0},"addOn":{"type":"integer","minimum":0},"perDownloadLimit":{"type":"integer","minimum":0}}}]},"upgradeUrl":{"anyOf":[{"type":"null"},{"type":"string","format":"uri"}]}}}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A current delegated OAuth grant and selected account are required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Free usage allowance is exhausted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The request exceeded its response deadline. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/search-field-values":{"post":{"tags":["Searches"],"summary":"Search Field Values","description":"**Find safe categorical field values.**\n\nReturns at most 20 prefix-matched values for reviewed low-cardinality fields. Values with fewer than 25 matching records are suppressed; record counts are not returned. Delegated OAuth requests must include a UUID X-ListShack-Request-Id; successful responses return remaining free allowance in X-ListShack-Free-Usage.\n\n**Required ListShack capabilities:** `search.read`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["databaseId","field","prefix","values"],"properties":{"databaseId":{"type":"string"},"field":{"type":"string"},"prefix":{"type":"string"},"values":{"type":"array","maxItems":20,"items":{"type":"string","minLength":1,"maxLength":128}}}}}},"headers":{"X-ListShack-Free-Usage":{"description":"JSON-encoded delegated account usage after this successful call; quota values follow the shared usage contract.","schema":{"type":"string","maxLength":4096,"contentMediaType":"application/json","contentSchema":{"type":"object","required":["policyVersion","period","limit","used","remaining","resetsAt"],"additionalProperties":false,"properties":{"policyVersion":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._-]+$"},"period":{"type":"string","enum":["calendar_month_utc"]},"unlimited":{"type":"boolean"},"limit":{"type":["integer","null"],"minimum":1,"maximum":9007199254740991},"used":{"type":"integer","minimum":0,"maximum":9007199254740991},"remaining":{"type":["integer","null"],"minimum":0,"maximum":9007199254740991},"resetsAt":{"type":"string","maxLength":32,"format":"date-time","pattern":"^\\d{4}-\\d{2}-01T00:00:00(?:\\.000)?Z$"}}}}}}},"400":{"description":"Invalid or unsupported free search request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A delegated OAuth grant with search.read is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Free search is disabled or the database is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request ID conflicts with a prior call or authorization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The free monthly allowance is exhausted. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Search service is unavailable or incomplete. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read"],"parameters":[{"name":"X-ListShack-Request-Id","in":"header","required":false,"schema":{"type":"string"},"description":"Stable UUID used to make delegated request retries idempotent."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["database_id","field","prefix"],"additionalProperties":false,"properties":{"database_id":{"type":"string","minLength":1,"maxLength":100},"field":{"type":"string","minLength":1,"maxLength":64},"prefix":{"type":"string","minLength":1,"maxLength":32}}}}}}}},"/api/v1/count-records":{"post":{"tags":["Searches"],"summary":"Count Records","description":"**Count records with privacy controls.**\n\nCounts records using a fixed use case and bounded typed filter. Counts below 25 are suppressed; larger counts are rounded to multiples of 10. Mandatory dataset and legal policies are applied automatically. Delegated OAuth requests must include a UUID X-ListShack-Request-Id; successful responses return remaining free allowance in X-ListShack-Free-Usage.\n\n**Required ListShack capabilities:** `search.read`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["databaseId","count","countSuppressed","appliedPolicies","policyVersion","datasetVersion","criteria"],"properties":{"databaseId":{"type":"string"},"count":{"type":["integer","null"],"minimum":0},"countSuppressed":{"type":"boolean"},"appliedPolicies":{"type":"array","items":{"type":"string"}},"policyVersion":{"type":"string"},"datasetVersion":{"type":"string"},"criteria":{"anyOf":[{"$ref":"#/components/schemas/TypedFilterNode"},{"type":"null"}]}}}}},"headers":{"X-ListShack-Free-Usage":{"description":"JSON-encoded delegated account usage after this successful call; quota values follow the shared usage contract.","schema":{"type":"string","maxLength":4096,"contentMediaType":"application/json","contentSchema":{"type":"object","required":["policyVersion","period","limit","used","remaining","resetsAt"],"additionalProperties":false,"properties":{"policyVersion":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._-]+$"},"period":{"type":"string","enum":["calendar_month_utc"]},"unlimited":{"type":"boolean"},"limit":{"type":["integer","null"],"minimum":1,"maximum":9007199254740991},"used":{"type":"integer","minimum":0,"maximum":9007199254740991},"remaining":{"type":["integer","null"],"minimum":0,"maximum":9007199254740991},"resetsAt":{"type":"string","maxLength":32,"format":"date-time","pattern":"^\\d{4}-\\d{2}-01T00:00:00(?:\\.000)?Z$"}}}}}}},"400":{"description":"Invalid or unsupported free search request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A delegated OAuth grant with search.read is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Free search is disabled or the database is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request ID conflicts with a prior call or authorization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The free monthly allowance is exhausted. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Search service is unavailable or incomplete. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read"],"parameters":[{"name":"X-ListShack-Request-Id","in":"header","required":false,"schema":{"type":"string"},"description":"Stable UUID used to make delegated request retries idempotent."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["database_id","use_case"],"additionalProperties":false,"if":{"properties":{"database_id":{"enum":["bizteladdr","vinconsumer"]}},"required":["database_id"]},"then":{"properties":{"use_case":{"const":"direct_mail"}}},"else":{"if":{"properties":{"database_id":{"const":"consumercells2"}},"required":["database_id"]},"then":{"properties":{"use_case":{"enum":["telemarketing","sms","direct_mail"]}}}},"properties":{"database_id":{"type":"string","enum":["consumeremteladdr262","bizteladdr","vinconsumer","consumercells2"]},"use_case":{"type":"string","enum":["telemarketing","sms","email","direct_mail"],"description":"Select a fixed server-owned compliance and data-integrity policy."},"filter":{"$ref":"#/components/schemas/TypedFilterNode"}}}}}}}},"/api/v1/searches":{"post":{"tags":["Searches"],"summary":"Create Search","description":"**Create an owned, policy-bound search.**\n\nAccepts a fixed use-case enum and bounded typed filter over stable logical field names. The API applies mandatory dataset and use-case policies and stores an immutable, expiring snapshot. Raw SQL, OpenSearch DSL and physical index names are not accepted. Successful delegated calls consume one free account call; include X-ListShack-Request-Id for idempotent retries.\n\n**Required ListShack capabilities:** `search.read`","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["status","searchId","expiresAt","replayed","databaseId","datasetVersion","policyVersion","criteria","appliedPolicies","count","countSuppressed"],"properties":{"count":{"type":["integer","null"],"minimum":0},"countSuppressed":{"type":"boolean"},"status":{"type":"string","enum":["prepared"]},"searchId":{"type":"string","format":"uuid"},"expiresAt":{"type":"string","format":"date-time","description":"Stored UTC expiry of this owned handle. Replaying creation does not extend it."},"replayed":{"type":"boolean"},"databaseId":{"type":"string"},"datasetVersion":{"type":"string"},"policyVersion":{"type":"string"},"criteria":{"anyOf":[{"$ref":"#/components/schemas/TypedFilterNode"},{"type":"null"}]},"appliedPolicies":{"type":"array","items":{"type":"string"}}}}}},"headers":{"X-ListShack-Free-Usage":{"description":"JSON-encoded delegated account usage after this successful call; quota values follow the shared usage contract.","schema":{"type":"string","maxLength":4096,"contentMediaType":"application/json","contentSchema":{"type":"object","required":["policyVersion","period","limit","used","remaining","resetsAt"],"additionalProperties":false,"properties":{"policyVersion":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._-]+$"},"period":{"type":"string","enum":["calendar_month_utc"]},"unlimited":{"type":"boolean"},"limit":{"type":["integer","null"],"minimum":1,"maximum":9007199254740991},"used":{"type":"integer","minimum":0,"maximum":9007199254740991},"remaining":{"type":["integer","null"],"minimum":0,"maximum":9007199254740991},"resetsAt":{"type":"string","maxLength":32,"format":"date-time","pattern":"^\\d{4}-\\d{2}-01T00:00:00(?:\\.000)?Z$"}}}}}}},"400":{"description":"Invalid database, use case, filter or client request ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid/expired token or insufficient ListShack capability.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown database or disabled search route.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflicting idempotency key or stale search snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The free monthly allowance is exhausted. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Search service unavailable or incomplete. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read"],"parameters":[{"name":"X-ListShack-Request-Id","in":"header","required":false,"schema":{"type":"string"},"description":"Stable UUID used to make delegated request retries idempotent."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["database_id","client_request_id","use_case"],"additionalProperties":false,"if":{"properties":{"database_id":{"enum":["bizteladdr","vinconsumer"]}},"required":["database_id"]},"then":{"properties":{"use_case":{"const":"direct_mail"}}},"else":{"if":{"properties":{"database_id":{"const":"consumercells2"}},"required":["database_id"]},"then":{"properties":{"use_case":{"enum":["telemarketing","sms","direct_mail"]}}}},"properties":{"database_id":{"type":"string","enum":["consumeremteladdr262","bizteladdr","vinconsumer","consumercells2"]},"client_request_id":{"type":"string","format":"uuid"},"use_case":{"type":"string","enum":["telemarketing","sms","email","direct_mail"],"description":"Select a fixed server-owned compliance and data-integrity policy."},"filter":{"$ref":"#/components/schemas/TypedFilterNode"}}}}}}}},"/api/v1/searches/{id}/preview":{"post":{"tags":["Searches"],"summary":"Preview Records","description":"**Preview masked records from an owned search.**\n\nReturns a small, masked sample from the unchanged server-owned search snapshot. Requires a current paid plan and explicit records.preview capability. Uses the owner-approved versioned field and masking rules; at most three rows and no credit spend.\n\n**Required ListShack capabilities:** `search.read`, `records.preview`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["searchId","databaseId","previewPolicyVersion","records"],"properties":{"searchId":{"type":"string","format":"uuid"},"databaseId":{"type":"string"},"previewPolicyVersion":{"type":"string"},"records":{"type":"array","maxItems":3,"items":{"type":"object","additionalProperties":{"type":["string","number","null"]}}}}}}}},"400":{"description":"Invalid preview request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"An eligible paid plan is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The delegated grant lacks preview capability.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Preview is disabled or the owned search is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The search policy or snapshot is stale.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"The preview privacy policy is not approved or search is unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read","records.preview"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Owned search UUID returned by POST /api/v1/searches."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["limit"],"additionalProperties":false,"properties":{"limit":{"type":"integer","minimum":1,"maximum":3}}}}}}}},"/api/v1/purchases/quote":{"post":{"tags":["Purchases"],"summary":"Quote Purchase","description":"**Quote an owned search purchase.**\n\nComputes the exact dictionary-priced credit effect for an owned search and requested count before human confirmation. The quote does not reserve or spend credits; purchase submission recomputes and checks it.\n\n**Required ListShack capabilities:** `search.read`, `lists.purchase`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["searchId","count","estimatedCreditEffect"],"properties":{"searchId":{"type":"string","format":"uuid"},"count":{"type":"integer"},"estimatedCreditEffect":{"type":"object","required":["credits","unit"],"properties":{"credits":{"type":"integer","minimum":0},"unit":{"type":"string","enum":["ListShack credits"]}}}}}}}},"400":{"description":"Invalid quote request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"An eligible paid plan is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The grant, account role, purchase capability, or per-download limit does not permit this quote.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Purchasing is disabled or the owned search is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The search snapshot is stale or the account limit requires repair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Search service unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read","lists.purchase"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["search_id","count","fields","name"],"properties":{"search_id":{"type":"string","format":"uuid","description":"Owned search snapshot returned by POST /api/v1/searches."},"count":{"type":"integer","minimum":1,"maximum":100000},"fields":{"type":"array","minItems":1,"maxItems":200,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$"}},"name":{"type":"string","minLength":1,"maxLength":200}}}}}}}},"/api/v1/purchases":{"post":{"tags":["Purchases"],"summary":"Purchase List","description":"**Purchase records from an owned search snapshot.**\n\nReserves credits and creates a durable purchase from the unchanged query snapshot stored on an owned search. Caller-provided filters, DSL and index names are rejected. This operation remains disabled until isolated staging purchase acceptance is complete.\n\n**Required ListShack capabilities:** `search.read`, `lists.purchase`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["id","state","ready","count","credits"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string"},"ready":{"type":"boolean"},"count":{"type":"integer","minimum":0},"credits":{"type":"integer","minimum":0},"url":{"type":["string","null"],"format":"uri-reference"},"error":{"type":["string","null"]}}}}}},"400":{"description":"Invalid purchase request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Paid plan or sufficient credits are required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The grant, account role, verification status, purchase capability, or per-download limit does not permit this purchase.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Purchasing is disabled or the owned search is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict, account allocation requiring repair, or stale search state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Search or checkout service unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read","lists.purchase"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["search_id","request_id","count","fields","name","expected_credits"],"properties":{"search_id":{"type":"string","format":"uuid","description":"Owned search snapshot returned by POST /api/v1/searches."},"request_id":{"type":"string","format":"uuid","description":"Caller-generated idempotency key; identical retries return the prior purchase state."},"count":{"type":"integer","minimum":1,"maximum":100000},"fields":{"type":"array","minItems":1,"maxItems":200,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$"}},"name":{"type":"string","minLength":1,"maxLength":200},"expected_credits":{"type":"integer","minimum":0,"description":"Credit quote shown to the user before confirmation; the API recomputes and verifies it before reserving credits."}}}}}}}},"/api/v1/purchases/{id}":{"get":{"tags":["Purchases"],"summary":"Get Purchase Status","description":"**Read an owned purchase status.**\n\nReturns durable state for a purchase created by the current delegated OAuth grant.\n\n**Required ListShack capabilities:** `search.read`, `lists.purchase`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["id","state","ready","count","credits"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string"},"ready":{"type":"boolean"},"count":{"type":"integer","minimum":0},"credits":{"type":"integer","minimum":0},"url":{"type":["string","null"],"format":"uri-reference"},"error":{"type":["string","null"]}}}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid/expired token or insufficient ListShack capability.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Purchase not found for this grant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Checkout service unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read","lists.purchase"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Purchase request UUID returned from POST /api/v1/purchases."}]}},"/api/v1/purchases/confirmation-links":{"post":{"tags":["Purchases"],"summary":"Create Purchase Approval Link","description":"**Create a human confirmation link for a purchase.**\n\nFor clients that cannot show an in-chat confirmation prompt. Quotes the exact purchase and returns a short-lived signed link the person who connected the agent opens in ListShack to approve it. Creating the link spends nothing; poll GET /api/v1/purchases/{id} with the returned purchaseId.\n\n**Required ListShack capabilities:** `search.read`, `lists.purchase`","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid purchase request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"An eligible paid plan is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The grant does not permit purchases.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Purchasing is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The quote could not be verified.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Delegated agent traffic limit reached. Traffic admission uses RATE_LIMITED, independently of successful-call quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until the relevant quota or traffic window resets.","schema":{"type":"integer","minimum":1}}}},"503":{"description":"Confirmation links are unavailable. REQUEST_TIMEOUT ends the response after 20 seconds. RESPONSE_TOO_LARGE rejects a response exceeding 1048576 payload bytes before headers start; an oversized partial stream is closed. Retry a mutating or metered request using its original request ID; a durable transaction may already have been accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-listshack-capabilities":["search.read","lists.purchase"]}}},"components":{"securitySchemes":{"ListShackOAuth":{"type":"oauth2","description":"Supabase Auth Authorization Code with PKCE. OAuth scopes identify the user; ListShack capabilities are granted and enforced separately.","flows":{"authorizationCode":{"authorizationUrl":"https://dev.listshack.io/supabase/auth/v1/oauth/authorize","tokenUrl":"https://dev.listshack.io/supabase/auth/v1/oauth/token","scopes":{"openid":"Authenticate the user","profile":"Read basic profile claims","email":"Read email claim","phone":"Read phone claims","offline_access":"Request refresh-token access"}}},"x-pkce":true}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string"},"retryAfterSeconds":{"type":"integer","minimum":1},"resetsAt":{"type":"string","format":"date-time"},"dimension":{"type":"string","enum":["account","client","credential","operation"]},"required_capability":{"type":"string"},"required_capabilities":{"type":"array","items":{"type":"string"}}}},"TypedFilterNode":{"oneOf":[{"type":"object","required":["and"],"additionalProperties":false,"properties":{"and":{"type":"array","minItems":1,"maxItems":8,"items":{"$ref":"#/components/schemas/TypedFilterNode"}}}},{"type":"object","required":["or"],"additionalProperties":false,"properties":{"or":{"type":"array","minItems":1,"maxItems":8,"items":{"$ref":"#/components/schemas/TypedFilterNode"}}}},{"type":"object","required":["not"],"additionalProperties":false,"properties":{"not":{"$ref":"#/components/schemas/TypedFilterNode"}}},{"type":"object","required":["field","operator"],"additionalProperties":false,"properties":{"field":{"type":"string","enum":["state","city","county","age","gender","homeowner","make","modelYear"]},"operator":{"type":"string","enum":["exists","missing"]}}},{"type":"object","required":["field","operator","value"],"additionalProperties":false,"properties":{"field":{"type":"string","enum":["state","city","county","age","gender","homeowner","make","modelYear"]},"operator":{"type":"string","enum":["eq","neq","gt","gte","lt","lte","in","like"]},"value":{"oneOf":[{"type":"string","maxLength":128},{"type":"number"},{"type":"boolean"},{"type":"array","minItems":1,"maxItems":20,"items":{"oneOf":[{"type":"string","maxLength":128},{"type":"number"},{"type":"boolean"}]}}]}}}]}}}}