{"openapi":"3.1.0","info":{"version":"0.1.0","title":"Relevan API","description":"Search relevance optimization platform API. AI agents: read https://feat-650-agent-skills.api.dev.relevan.dev/llms.txt before you use the API. It gives the steps that an agent must do, such as the steps after you create an index, and it links the skills and the other Relevan documents. To set up search from the start, follow https://feat-650-agent-skills.api.dev.relevan.dev/skills/relevan-setup/SKILL.md.","contact":{"name":"Relevan Support","url":"https://relevan.dev","email":"support@relevan.dev"}},"servers":[{"url":"https://feat-650-agent-skills.api.dev.relevan.dev"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Org-scoped API key. Session-cookie auth (used by the console) is also accepted but isn't representable as an OpenAPI security scheme."}},"schemas":{"OrganizationsList":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}},"Organization":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Unique organization identifier"},"slug":{"type":"string","example":"relevan-dev","description":"URL-safe organization slug. Accepted anywhere an `orgId` path parameter is expected, interchangeably with `id`."},"name":{"type":"string","example":"Relevan Dev","description":"Organization display name"}},"required":["id","slug","name"]},"ErrorResponse":{"type":"object","properties":{"message":{"type":"string","example":"Index not found","description":"Error message"},"error":{"type":"string","example":"No index found with the provided name","description":"Detailed error information"}},"required":["message"]},"MessageResponse":{"type":"object","properties":{"message":{"type":"string","example":"Index archived and deletion queued","description":"Response message"}},"required":["message"]},"IndexesList":{"type":"array","items":{"$ref":"#/components/schemas/Index"}},"Index":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Unique index identifier"},"organizationId":{"type":"string","example":"org_123456789","description":"Organization ID that owns this index"},"indexName":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"displayName":{"type":["string","null"],"maxLength":128,"example":"Product Catalog","description":"Display name shown in the UI"},"description":{"type":["string","null"],"maxLength":512,"example":"Product catalog index","description":"Index description"},"status":{"type":"string","enum":["creating","ready","failed"],"example":"ready","description":"Current index lifecycle status"},"readyAt":{"type":["string","null"],"example":"2024-01-15T10:31:12.000Z","description":"The first time the index status became ready. Null if it was never ready."},"failedAt":{"type":["string","null"],"example":null,"description":"The first time the index status became failed. Null if it never failed."},"createdAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Index creation timestamp"},"updatedAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Last update timestamp"}},"required":["id","organizationId","indexName","displayName","description","status","readyAt","failedAt","createdAt","updatedAt"]},"CreatedIndex":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Unique index identifier"},"organizationId":{"type":"string","example":"org_123456789","description":"Organization ID that owns this index"},"indexName":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"displayName":{"type":["string","null"],"maxLength":128,"example":"Product Catalog","description":"Display name shown in the UI"},"description":{"type":["string","null"],"maxLength":512,"example":"Product catalog index","description":"Index description"},"status":{"type":"string","enum":["creating","ready","failed"],"example":"ready","description":"Current index lifecycle status"},"readyAt":{"type":["string","null"],"example":"2024-01-15T10:31:12.000Z","description":"The first time the index status became ready. Null if it was never ready."},"failedAt":{"type":["string","null"],"example":null,"description":"The first time the index status became failed. Null if it never failed."},"createdAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Index creation timestamp"},"updatedAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Last update timestamp"},"consoleUrl":{"type":"string","example":"https://feat-650-agent-skills.console.dev.relevan.dev/org_123456789/indexes","description":"The console index list page, which shows live build progress. Give this link to the user right away, in your next message, before you deploy a mapping or upload documents. Do not wait and give the link only in a final summary. Tell the user to open the link to monitor the progress."},"skillUrl":{"type":"string","example":"/v1/org_123456789/indexes/products/skill","description":"The skill doc for this index. Fetch it with GET before you draft or deploy a mapping — it gives the mapping guidance now, and the search guidance once a mapping exists."}},"required":["id","organizationId","indexName","displayName","description","status","readyAt","failedAt","createdAt","updatedAt","consoleUrl","skillUrl"]},"CreateIndex":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"displayName":{"type":"string","maxLength":128,"example":"Product Catalog","description":"Display name shown in the UI"},"description":{"type":"string","maxLength":512,"example":"Product catalog index","description":"Index description"}},"required":["name"]},"IndexDetail":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Unique index identifier"},"organizationId":{"type":"string","example":"org_123456789","description":"Organization ID that owns this index"},"indexName":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"displayName":{"type":["string","null"],"maxLength":128,"example":"Product Catalog","description":"Display name shown in the UI"},"description":{"type":["string","null"],"maxLength":512,"example":"Product catalog index","description":"Index description"},"status":{"type":"string","enum":["creating","ready","failed"],"example":"ready","description":"Current index lifecycle status"},"readyAt":{"type":["string","null"],"example":"2024-01-15T10:31:12.000Z","description":"The first time the index status became ready. Null if it was never ready."},"failedAt":{"type":["string","null"],"example":null,"description":"The first time the index status became failed. Null if it never failed."},"createdAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Index creation timestamp"},"updatedAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Last update timestamp"},"documentsAccepted":{"type":"integer","minimum":0,"example":1215854,"description":"Documents accepted into Postgres, the canonical count"},"documentsIndexed":{"type":"integer","minimum":0,"example":146000,"description":"Documents present in the searchable OpenSearch instance"},"documentsAcceptedChangedAt":{"type":["string","null"],"example":"2024-01-15T10:30:00.000Z","description":"When documentsAccepted last changed, in either direction. Null if the index has never accepted a document."},"readyToSearch":{"type":"boolean","example":false,"description":"True once OpenSearch holds every accepted document"}},"required":["id","organizationId","indexName","displayName","description","status","readyAt","failedAt","createdAt","updatedAt","documentsAccepted","documentsIndexed","documentsAcceptedChangedAt","readyToSearch"]},"UpdateIndex":{"type":"object","properties":{"displayName":{"type":"string","maxLength":128,"example":"Product Catalog","description":"Display name shown in the UI"},"description":{"type":"string","maxLength":512,"example":"Product catalog index","description":"Index description"}}},"DocumentsList":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/Document"}},"total":{"type":"integer","minimum":0,"example":42,"description":"Total number of active documents in the index"},"page":{"type":"integer","exclusiveMinimum":0,"example":1},"limit":{"type":"integer","exclusiveMinimum":0,"example":20}},"required":["documents","total","page","limit"]},"Document":{"type":"object","properties":{"id":{"type":"string","example":"doc_42a1b8d9","description":"Unique document identifier"},"indexName":{"type":"string","example":"products","description":"Index name"},"content":{"type":"object","additionalProperties":{},"description":"Document content. All fields must be declared in the index mapping."},"createdAt":{"type":"string","format":"date-time","example":"2024-01-15T10:30:00Z","description":"Document creation timestamp"},"updatedAt":{"type":"string","format":"date-time","example":"2024-01-15T10:30:00Z","description":"Document last update timestamp"}},"required":["id","indexName","content","createdAt","updatedAt"]},"StorageLimitErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["storage_limit_exceeded"],"description":"Stable, machine-readable reason. Branch on this, not on `message`."},"limitBytes":{"type":"integer","example":2147483648,"description":"Storage bytes permitted at the organization's tier."},"usedBytes":{"type":"integer","example":2100000000,"description":"Bytes already stored before this write."},"incomingBytes":{"type":"integer","example":50000000,"description":"Net bytes this write would add."},"remainingBytes":{"type":"integer","example":47483648,"description":"Bytes free before this write."}},"required":["code","limitBytes","usedBytes","incomingBytes","remainingBytes"]}]},"CreateDocument":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_.:-]+$","example":"sku-12345","description":"Caller-supplied document ID, unique within the index. Alphanumeric, underscore, period, colon, and hyphen only."},"content":{"type":"object","additionalProperties":{},"description":"Document content. All fields must be declared in the index mapping."}},"required":["id","content"]},"BulkIngestResponse":{"type":"object","properties":{"accepted":{"type":"integer","minimum":0,"example":50,"description":"Number of documents accepted for indexing"},"documentIds":{"type":"array","items":{"type":"string"},"description":"IDs of the accepted documents in order"}},"required":["accepted","documentIds"]},"BulkValidationErrorResponse":{"type":"object","properties":{"message":{"type":"string"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/DocumentValidationError"}}},"required":["message","errors"]},"DocumentValidationError":{"type":"object","properties":{"documentIndex":{"type":"integer","minimum":0,"example":2,"description":"Zero-based index of the failing document in the request array"},"field":{"type":"string","example":"price"},"message":{"type":"string","example":"Field 'price' must be of kind 'number'."}},"required":["documentIndex","field","message"]},"BulkIngestRequest":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/BulkIngestItem"},"minItems":1,"maxItems":1000,"description":"Array of documents to ingest (max 1000 per request)"}},"required":["documents"]},"BulkIngestItem":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":512,"pattern":"^[A-Za-z0-9_.:-]+$","example":"sku-12345","description":"Caller-supplied document ID, unique within the index. Alphanumeric, underscore, period, colon, and hyphen only."},"content":{"type":"object","additionalProperties":{},"description":"Document content. All fields must be declared in the index mapping."}},"required":["id","content"]},"UpdateDocument":{"type":"object","properties":{"content":{"type":"object","additionalProperties":{},"description":"Document content. All fields must be declared in the index mapping."}},"required":["content"]},"MappingsList":{"type":"array","items":{"$ref":"#/components/schemas/MappingRevision"}},"MappingRevision":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Unique mapping revision identifier"},"revision":{"type":"integer","exclusiveMinimum":0,"example":1,"description":"Monotonic mapping revision number (starts at 1 within an index)"},"relevanMapping":{"$ref":"#/components/schemas/Mapping"},"relevanMappingYaml":{"type":"string","example":"fields:\n  name:\n    use: [searchable]\n","description":"Canonicalized Relevan mapping YAML"},"relevanMappingHash":{"type":"string","example":"3b7c4a1d...","description":"sha256 hash of canonical Relevan mapping YAML"},"createdBy":{"type":["string","null"],"example":"550e8400-e29b-41d4-a716-446655440000","description":"User id that created the revision (nullable)"},"createdAt":{"type":"string","example":"2024-01-15T10:30:00.000Z","description":"Mapping revision creation timestamp"}},"required":["id","revision","relevanMapping","relevanMappingYaml","relevanMappingHash","createdBy","createdAt"]},"Mapping":{"type":"object","properties":{"fields":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/FieldMapping"},"example":{"name":{"use":["searchable","filterable"]},"price":{"use":["filterable","sortable"],"kind":"number"}},"description":"Field mappings by field name"},"language":{"type":"string","enum":["english","none"],"example":"english","description":"Language for every text field that does not name its own. Defaults to english."}},"required":["fields"],"description":"Parsed Relevan mapping JSON"},"FieldMapping":{"type":"object","properties":{"use":{"type":"array","items":{"type":"string","enum":["searchable","filterable","sortable","aggregatable","autocompletable","highlightable"],"example":"searchable","description":"Intended query capability for this field"},"minItems":1,"description":"Intended query capabilities for this field"},"kind":{"type":"string","enum":["text","id","number","date","boolean","object","array","geo_point"],"example":"text","description":"Field data type (inferred if omitted)"},"language":{"type":"string","enum":["english","none"],"example":"english","description":"Overrides the mapping language for this field"}},"required":["use"]},"UpdateMapping":{"type":"object","properties":{"fields":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/FieldMapping"},"example":{"name":{"use":["searchable","filterable"]},"price":{"use":["filterable","sortable"],"kind":"number"}},"description":"Field mappings by field name"},"language":{"type":"string","enum":["english","none"],"example":"english","description":"Language for every text field that does not name its own. Defaults to english."}},"required":["fields"]},"SearchResult":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchHit"}},"searchContext":{"$ref":"#/components/schemas/SearchContext"},"took":{"type":"integer","minimum":0,"description":"OpenSearch took ms"}},"required":["results","searchContext","took"]},"SearchHit":{"type":"object","properties":{"id":{"type":"string","example":"sku-12345"},"score":{"type":["number","null"],"example":12.4},"document":{"type":"object","additionalProperties":{},"description":"The matched document's content"},"highlights":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Highlighted text snippets by field"},"explanation":{"type":"string","example":"\"neon tetra\" in description (4.20). Total score: 12.400","description":"Human-readable description of why this document matched"},"matchedFields":{"type":"array","items":{"type":"string"},"description":"Base field names that contributed to this hit's score"},"matchedTerms":{"type":"array","items":{"type":"string"},"description":"Indexed terms that contributed to this hit's score"}},"required":["id","score","document","explanation","matchedFields","matchedTerms"]},"SearchContext":{"type":"object","properties":{"queryUsed":{"type":"string","description":"The query actually executed, post-enrichment"},"totalHits":{"type":"integer","minimum":0},"matchedTerms":{"type":"array","items":{"type":"string"},"description":"Union of matched terms across all returned hits"},"topContributingFields":{"type":"array","items":{"type":"string"},"description":"Fields that contributed score, ordered by contribution descending"},"titleField":{"type":["string","null"],"description":"Field holding each document's human-readable label, resolved from the index mapping. Null when the index has no text field.","example":"title"},"scoringSummary":{"type":"string"},"suggestions":{"type":"string","description":"Guidance for reformulating the query"},"searchableFields":{"type":"array","items":{"type":"string"},"description":"All fields configured as searchable on this index"},"warnings":{"type":"array","items":{"type":"string"},"example":["Ignored boost terms that are not in the query: [term]. Boost only a word that is in the query."],"description":"Problems with the request that the search worked around, for example boost terms that are not in the query. Absent when there are none."},"fallback":{"type":"object","properties":{"kind":{"type":"string","enum":["relaxedMinimumShouldMatch"]},"originalMinimumShouldMatch":{"type":"string","example":"60%","description":"The share of query terms that the first query required."},"minimumShouldMatch":{"type":"string","example":"1","description":"The share of query terms that the fallback query required."}},"required":["kind","originalMinimumShouldMatch","minimumShouldMatch"],"description":"Present when the first query of a long query found no document, and a less strict query found the results. Absent otherwise."},"sessionId":{"type":"string","example":"8f14e45f-ceea-467e-a1a4-8f6c1c1a1a1a","description":"This request's session identifier — the request's sessionId echoed back, or a new one when it was omitted. Send it back on the next call to continue this session."},"queryId":{"type":"string","example":"3c2e6e0a-9b7a-4e8b-9e2f-1a2b3c4d5e6f","description":"This request's unique id. Send it as queryId on a POST /v1-beta/{orgId}/indexes/{indexName}/feedback call to report feedback about one of these results."}},"required":["queryUsed","totalHits","matchedTerms","topContributingFields","titleField","scoringSummary","suggestions","searchableFields","sessionId","queryId"]},"SearchQuotaErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["search_quota_exceeded"],"description":"Stable, machine-readable reason. Branch on this, not on `message`."},"limit":{"type":"integer","example":10000,"description":"Searches permitted this calendar month at the organization's tier."},"used":{"type":"integer","example":10000,"description":"Searches the organization got this calendar month. A rejected request does not count."},"resetAt":{"type":"string","format":"date-time","example":"2026-10-01T00:00:00.000Z","description":"Start of the next calendar month, when the quota resets."}},"required":["code","limit","used","resetAt"]}]},"LimitErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"code":{"type":"string","enum":["rate_limit_exceeded"],"description":"Stable, machine-readable reason. Branch on this, not on `message`."},"limit":{"type":"integer","example":60,"description":"Requests permitted in the window at the organization's tier."},"remaining":{"type":"integer","example":0,"description":"Requests left in the current window."},"resetAt":{"type":"string","format":"date-time","example":"2026-01-01T00:01:00.000Z","description":"When the current window rolls over."},"retryAfterSeconds":{"type":"integer","example":42,"description":"Whole seconds to wait before retrying. Mirrors the `Retry-After` header."}},"required":["code","limit","remaining","resetAt","retryAfterSeconds"]}]},"SearchRequest":{"type":"object","properties":{"query":{"type":"string","minLength":1,"example":"neon tetra","description":"The search query text"},"filters":{"type":"array","items":{"$ref":"#/components/schemas/SearchFilter"},"description":"Filters, ANDed together. Exact-match, in, or range (date/number fields)."},"boost":{"type":"object","additionalProperties":{"type":"number"},"example":{"getting":2},"description":"Per-term weight multipliers. Adds an extra match clause for each term across searchable fields; it does not change how the base query matches. Each term must occur in the query. The search ignores a term that does not, and names it in searchContext.warnings."},"from":{"type":"integer","minimum":0,"maximum":500,"example":0,"description":"Result offset for pagination (max 500)"},"size":{"type":"integer","exclusiveMinimum":0,"maximum":100,"example":10,"description":"Number of results to return (max 100)"},"sessionId":{"type":"string","minLength":1,"maxLength":200,"example":"8f14e45f-ceea-467e-a1a4-8f6c1c1a1a1a","description":"Groups requests from the same conversation. Send back the sessionId from the previous response to continue a session; omit it to start a new one."},"customerId":{"type":"string","minLength":1,"maxLength":200,"example":"user_48291","description":"Caller-supplied end-user identifier, stable across sessions. Hashed before storage; never logged or returned in plain text."}},"required":["query"]},"SearchFilter":{"anyOf":[{"type":"object","properties":{"field":{"type":"string","minLength":1,"example":"category"},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}],"example":"aquarium"}},"required":["field","value"]},{"type":"object","properties":{"field":{"type":"string","minLength":1,"example":"category"},"values":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"minItems":1,"example":["aquarium","terrarium"]}},"required":["field","values"]},{"$ref":"#/components/schemas/SearchRangeFilter"}]},"SearchRangeFilter":{"type":"object","properties":{"field":{"type":"string","minLength":1,"example":"publishedAt"},"gte":{"anyOf":[{"type":"string"},{"type":"number"}],"example":"2026-01-01"},"lte":{"anyOf":[{"type":"string"},{"type":"number"}],"example":"2026-12-31"}},"required":["field"]},"FeedbackRequest":{"type":"object","properties":{"actionName":{"type":"string","enum":["click","llm_judgment","conversion"],"description":"click: a real end user picked this result. llm_judgment: an agent judged this result relevant, without a human confirming it. conversion: a closing event confirmed this result was right — a purchase, a hire, or another outcome you define."},"source":{"type":"string","enum":["production","eval"],"default":"production","description":"production: this feedback comes from real caller traffic. eval: this feedback comes from a test suite or benchmark run, not a real user or agent session. Defaults to production."},"queryId":{"type":"string","minLength":1,"maxLength":200,"example":"3c2e6e0a-9b7a-4e8b-9e2f-1a2b3c4d5e6f","description":"The queryId from a prior search response's searchContext. Send it when this feedback concerns one specific search."},"objectId":{"type":"string","minLength":1,"maxLength":512,"example":"sku-12345","description":"The id of the result this feedback is about. Required for type click and llm_judgment."},"position":{"type":"integer","minimum":0,"example":0,"description":"The rank position the result held in the response, when known."},"label":{"type":"string","minLength":1,"maxLength":200,"example":"hire","description":"A short name for a conversion event, for example hire or purchase."},"sessionId":{"type":"string","minLength":1,"maxLength":200,"example":"8f14e45f-ceea-467e-a1a4-8f6c1c1a1a1a","description":"The same sessionId used on the search request this feedback concerns."},"customerId":{"type":"string","minLength":1,"maxLength":200,"example":"user_48291","description":"The same customerId used on the search request this feedback concerns."}},"required":["actionName"]}},"parameters":{}},"paths":{"/v1/organizations":{"get":{"tags":["Organizations"],"summary":"List organizations accessible to the caller","description":"Resolves the caller's `x-api-key` or session cookie to the organization(s) it can access. An org-scoped API key always resolves to exactly one organization — this is the entry point for an agent that holds a key but doesn't yet know its `orgId`. Either `id` or `slug` from the response works as the `orgId` path parameter on `/v1/{orgId}/...` routes.","responses":{"200":{"description":"Organizations the caller can access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationsList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}":{"delete":{"tags":["Organizations"],"summary":"Delete an organization","description":"Permanently delete the organization, with its indexes, documents, API keys, members, and invitations. Only an owner can do this, with a session. An API key cannot. Search cleanup happens asynchronously.","responses":{"200":{"description":"Organization deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The caller is not an owner, or used an API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes":{"get":{"tags":["Indexes"],"summary":"List all indexes","description":"Retrieve a list of all indexes in the organization.","parameters":[{"schema":{"type":"integer","exclusiveMinimum":0,"example":1,"description":"Page number for pagination"},"required":false,"description":"Page number for pagination","name":"page","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"example":10,"description":"Number of results per page"},"required":false,"description":"Number of results per page","name":"limit","in":"query"}],"responses":{"200":{"description":"List of indexes retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexesList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"error":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Indexes"],"summary":"Create a new index","description":"Create a new search index in the organization. Right after you create the index, give the user the `consoleUrl` link from the response, in your next message. Do this before you deploy a mapping or upload documents. Do not wait and give the link only in a final summary. Tell the user to open the link to monitor the progress. Fetch `skillUrl` next, before you draft a mapping.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIndex"}}}},"responses":{"201":{"description":"Index created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIndex"}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Index with this name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}":{"get":{"tags":["Indexes"],"summary":"Get index by name","description":"Retrieve a specific index by its name, with the document counts that show how far the index has got through the asynchronous ingest pipeline.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"responses":{"200":{"description":"Index retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndexDetail"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Indexes"],"summary":"Update index metadata","description":"Update index metadata (name, description). To change field mappings, create a new mapping revision.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIndex"}}}},"responses":{"200":{"description":"Index updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Index"}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Indexes"],"summary":"Delete an index","description":"Archive and remove an index. Search cleanup happens asynchronously.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"responses":{"200":{"description":"Index archived and deletion queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/skill":{"get":{"tags":["Search"],"summary":"Get an agent-oriented skill doc for this index","description":"Returns a Markdown document describing this index's live schema and how to query it — meant for an LLM/agent to fetch once and use to drive `POST /indexes/{indexName}/search` calls without prior knowledge of the mapping.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"responses":{"200":{"description":"Skill document generated from the index's current mapping","content":{"text/markdown":{"schema":{"type":"string","description":"Skill document (Markdown)"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/documents":{"get":{"tags":["Documents"],"summary":"List documents in an index","description":"Get paginated active documents in a specific index.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0,"example":1,"description":"Page number"},"required":false,"description":"Page number","name":"page","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":100,"example":20,"description":"Results per page (max 100)"},"required":false,"description":"Results per page (max 100)","name":"limit","in":"query"}],"responses":{"200":{"description":"Documents retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentsList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Documents"],"summary":"Create a new document","description":"Creates a document in the index. All fields must be declared in the index mapping. Unknown fields are rejected.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDocument"}}}},"responses":{"201":{"description":"Document created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}}},"400":{"description":"Validation failed — unknown or mistyped fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Organization's storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageLimitErrorResponse"}}}},"404":{"description":"Index not found or has no mapping","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Document with this ID already exists in the index","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/documents/_bulk":{"post":{"tags":["Documents"],"summary":"Bulk ingest documents","description":"Ingest up to 1000 documents in a single request. If any document fails mapping validation, the entire request is rejected (no partial writes). Existing documents with matching IDs are upserted.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkIngestRequest"}}}},"responses":{"202":{"description":"Documents accepted for indexing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkIngestResponse"}}}},"400":{"description":"One or more documents failed mapping validation. No documents were written.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkValidationErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Organization's storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageLimitErrorResponse"}}}},"404":{"description":"Index not found or has no mapping","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/documents/:documentId":{"get":{"tags":["Documents"],"summary":"Get a single document","description":"Retrieve a specific active document by ID from an index.","parameters":[{"schema":{"type":"string"},"required":true,"name":"indexName","in":"path"},{"schema":{"type":"string","example":"doc_42a1b8d9","description":"Unique document identifier"},"required":true,"description":"Unique document identifier","name":"documentId","in":"path"}],"responses":{"200":{"description":"Document retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document or index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Documents"],"summary":"Update a document","description":"Replaces document content. All provided fields must be declared in the index mapping.","parameters":[{"schema":{"type":"string"},"required":true,"name":"indexName","in":"path"},{"schema":{"type":"string","example":"doc_42a1b8d9","description":"Unique document identifier"},"required":true,"description":"Unique document identifier","name":"documentId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDocument"}}}},"responses":{"200":{"description":"Document updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}}},"400":{"description":"Validation failed — unknown or mistyped fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Organization's storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageLimitErrorResponse"}}}},"404":{"description":"Document or index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Documents"],"summary":"Delete a document","description":"Tombstones a document in Aurora and enqueues removal from OpenSearch. The document will no longer appear in search results once processed.","parameters":[{"schema":{"type":"string"},"required":true,"name":"indexName","in":"path"},{"schema":{"type":"string","example":"doc_42a1b8d9","description":"Unique document identifier"},"required":true,"description":"Unique document identifier","name":"documentId","in":"path"}],"responses":{"200":{"description":"Document deletion queued successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document or index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/mappings":{"get":{"tags":["Mappings"],"summary":"List index mappings","description":"Retrieve a list of all mappings for an index.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"responses":{"200":{"description":"List of mappings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MappingsList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Mappings"],"summary":"Create index mapping","description":"Create a new field mapping revision for an index. Mapping revisions are immutable and stored in append-only history. To update mappings, create a new revision.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMapping"}}}},"responses":{"201":{"description":"Mapping revision created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MappingRevision"}}}},"400":{"description":"Invalid mapping","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/mappings/:mappingId":{"get":{"tags":["Mappings"],"summary":"Get index mapping","description":"Retrieve the mapping given the mapping ID.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"},{"schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000","description":"Mapping revision identifier"},"required":true,"description":"Mapping revision identifier","name":"mappingId","in":"path"}],"responses":{"200":{"description":"Mapping retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MappingRevision"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Index or mapping not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/{orgId}/indexes/{indexName}/search":{"post":{"tags":["Search"],"summary":"Search an index","description":"Execute a search query against an index. Returns the same rich, LLM-oriented result shape for every caller — direct API consumer or agent.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Search results","headers":{"X-Search-Quota-Limit":{"schema":{"type":"string","example":"10000","description":"Searches permitted this calendar month at the organization's tier."},"required":false,"description":"Searches permitted this calendar month at the organization's tier."},"X-Search-Quota-Remaining":{"schema":{"type":"string","example":"8970","description":"Searches left this calendar month, after this request."},"required":false,"description":"Searches left this calendar month, after this request."},"X-Search-Quota-Reset":{"schema":{"type":"string","format":"date-time","example":"2026-11-01T00:00:00.000Z","description":"Start of the next calendar month (UTC), when the quota resets."},"required":false,"description":"Start of the next calendar month (UTC), when the quota resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResult"}}}},"400":{"description":"Invalid filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Organization's monthly search quota for its tier is exhausted","headers":{"X-Search-Quota-Limit":{"schema":{"type":"string","example":"10000","description":"Searches permitted this calendar month at the organization's tier."},"required":false,"description":"Searches permitted this calendar month at the organization's tier."},"X-Search-Quota-Remaining":{"schema":{"type":"string","example":"8970","description":"Searches left this calendar month, after this request."},"required":false,"description":"Searches left this calendar month, after this request."},"X-Search-Quota-Reset":{"schema":{"type":"string","format":"date-time","example":"2026-11-01T00:00:00.000Z","description":"Start of the next calendar month (UTC), when the quota resets."},"required":false,"description":"Start of the next calendar month (UTC), when the quota resets."},"Retry-After":{"schema":{"type":"string","example":"1987200","description":"Seconds until the monthly quota resets."},"required":true,"description":"Seconds until the monthly quota resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuotaErrorResponse"}}}},"404":{"description":"Index not found, or has no searchable instance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Organization's search rate limit for its tier is exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitErrorResponse"}}}}}}},"/v1-beta/{orgId}/indexes/{indexName}/feedback":{"post":{"tags":["Feedback"],"summary":"Report feedback about a search result","description":"Report a click, an LLM relevance judgment, or a conversion event, attributed to the same sessionId and customerId a prior search used. Beta: this endpoint's contract may still change. See docs/search-feedback-logging-design.md.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9]([a-z0-9-]*[a-z0-9])?$","example":"products","description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)"},"required":true,"description":"URL-safe index name (lowercase alphanumeric + hyphens, unique within org)","name":"indexName","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}}},"responses":{"202":{"description":"Feedback accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"description":"Invalid feedback request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"webhooks":{}}