{"openapi":"3.1.0","info":{"title":"JustIdea Agency public API","version":"1.0.0","summary":"Read-only API for the public website of JustIdea Agency: search and read pages, starting prices of services and contact options.","description":"JustIdea Agency (justidea.agency) is a Polish e-commerce and performance marketing agency from Kraków: online stores (PrestaShop, WooCommerce), websites, SEO, paid ads, analytics, content and branding.\n\nThis API is **read-only** and exposes only what is published on the website. It never submits forms, books meetings or sends messages: to get in touch, give the user the contact link, e-mail address or phone number from `GET /api/v1/contact`. The same data is available over MCP at https://justidea.agency/mcp.\n\n**Authentication.** None required. An optional OAuth 2.1 bearer token (scope `site:read`, see https://justidea.agency/auth.md) identifies the agent and raises the rate limit. An invalid or expired token gets `401` with a `WWW-Authenticate` header pointing at https://justidea.agency/.well-known/oauth-protected-resource; `GET /api/v1/identity` always needs a token.\n\n**Rate limits.** 120 requests per 60 seconds per IP address, 600 per agent with a token. Every response carries `RateLimit-Policy` (IETF RateLimit header fields) and `X-RateLimit-Limit`. A `429` carries `Retry-After` (seconds) and `RateLimit` with the remaining quota (0). A batch counts as one request.\n\n**Errors.** Every 4xx and 5xx response is `application/problem+json` (RFC 9457) with `type`, `title`, `status`, `detail`, `instance` and a machine-readable `code`. Each `type` URI points at its section of https://justidea.agency/api.md.\n\n**Pagination.** `GET /api/v1/pages` is cursor-based: pass `next_cursor` from the response as `cursor` until it is `null`. The next page is also in the `Link: <...>; rel=\"next\"` header. Cursors are opaque.\n\n**Versioning and deprecation.** The major version is in the path (`/api/v1`). Within v1 changes are additive only: new endpoints, new optional parameters, new response fields. Clients must ignore unknown fields. A breaking change ships as `/api/v2`; v1 then keeps working and its responses carry a `Deprecation` header (RFC 9745) from the day the decision is made and a `Sunset` header (RFC 8594) with the removal date, at least 90 days later. `info.version` follows SemVer.\n\n**Batch and retries.** `POST /api/v1/batch` runs up to 10 GET operations in one request. All operations are read-only and have no side effects, so every request, including a batch, is safe to retry. An optional `Idempotency-Key` header on the batch is accepted and echoed back.\n\nAll prices are net starting prices (VAT excluded) as published on the website: PLN on Polish pages, EUR on English pages. The final quote depends on scope.","contact":{"name":"JustIdea Agency","email":"contact@justidea.agency","url":"https://justidea.agency/en/contact/"},"license":{"name":"Proprietary. Public content of justidea.agency, free to read and quote with attribution."}},"externalDocs":{"description":"Reference in Markdown: error types, limits, examples.","url":"https://justidea.agency/api.md"},"servers":[{"url":"https://justidea.agency","description":"justidea.agency"}],"security":[{},{"agentOAuth":["site:read"]}],"tags":[{"name":"content","description":"Search and read public pages."},{"name":"offer","description":"Services and their published starting prices."},{"name":"contact","description":"How a person can reach JustIdea Agency."},{"name":"agents","description":"Agent identity and batch reads."},{"name":"meta","description":"API description and status."}],"paths":{"/api/v1":{"get":{"operationId":"getApiRoot","tags":["meta"],"summary":"Describe API v1","description":"Entry point of API v1: what the API covers and the full URL of every endpoint.","responses":{"200":{"description":"API description.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRoot"}}}},"401":{"$ref":"#/components/responses/InvalidToken"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/health":{"get":{"operationId":"getHealth","tags":["meta"],"summary":"Check API health","description":"Whether the site catalog is loaded, with the number of pages. Returns 503 when the data is not available.","responses":{"200":{"description":"Healthy.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"401":{"$ref":"#/components/responses/InvalidToken"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Site data not available.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/v1/search":{"get":{"operationId":"searchSite","tags":["content"],"summary":"Search the website","description":"Search over the public pages of justidea.agency (services, pricing, case studies, company pages, city pages and blog posts in Polish and English). Returns titles, descriptions and URLs ranked by relevance; read a result with getPage.","parameters":[{"$ref":"#/components/parameters/Query"},{"$ref":"#/components/parameters/Lang"},{"$ref":"#/components/parameters/PageType"},{"$ref":"#/components/parameters/SearchLimit"}],"responses":{"200":{"description":"Search results.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResults"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/InvalidToken"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/api/v1/pages":{"get":{"operationId":"listPages","tags":["content"],"summary":"List pages","description":"Public pages, optionally filtered by kind and language, with cursor pagination.","parameters":[{"$ref":"#/components/parameters/PageType"},{"$ref":"#/components/parameters/Lang"},{"$ref":"#/components/parameters/PageLimit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"One page of results.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"},"Link":{"$ref":"#/components/headers/Link"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/InvalidToken"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/api/v1/page":{"get":{"operationId":"getPage","tags":["content"],"summary":"Read a page as Markdown","description":"The content of one public page as clean Markdown (no navigation, scripts or forms). Accepts a full URL, a path or the .md address of the page.","parameters":[{"$ref":"#/components/parameters/Url"}],"responses":{"200":{"description":"Page content.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageContent"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/InvalidToken"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/api/v1/services":{"get":{"operationId":"listServices","tags":["offer"],"summary":"List services and starting prices","description":"Service categories with their published net starting prices and packages, and the pages of every service. Polish pages quote PLN, English pages EUR. from_price null means the price is quoted individually. Use these numbers only with the page URL; do not state prices this endpoint did not return.","parameters":[{"$ref":"#/components/parameters/OfferLang"}],"responses":{"200":{"description":"Services and prices.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Services"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/InvalidToken"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/api/v1/contact":{"get":{"operationId":"getContactOptions","tags":["contact"],"summary":"Get contact options","description":"How a person can reach JustIdea Agency: e-mail, phone and the contact page in Polish or English. Nothing here submits forms: pass the link, e-mail or phone to the user.","parameters":[{"$ref":"#/components/parameters/Lang"}],"responses":{"200":{"description":"Contact options.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactOptions"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/InvalidToken"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/api/v1/identity":{"get":{"operationId":"getAgentIdentity","tags":["agents"],"summary":"Identify the calling agent","description":"Who the bearer token belongs to and which rate limit applies. Requires a token; without one returns 401 with WWW-Authenticate pointing at the protected resource metadata.","security":[{"agentOAuth":["site:read"]}],"responses":{"200":{"description":"The agent behind the token.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentIdentity"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/agent/identity":{"get":{"operationId":"getAgentIdentityWellKnown","tags":["agents"],"summary":"Identify the calling agent (agent-auth address)","description":"Same as getAgentIdentity, at the address agent-auth clients look for.","security":[{"agentOAuth":["site:read"]}],"responses":{"200":{"description":"The agent behind the token.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentIdentity"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/batch":{"post":{"operationId":"batchRead","tags":["agents"],"summary":"Run several reads in one request","description":"Runs 1 to 10 GET operations on /api/v1 endpoints (except batch, identity and the API documents) and returns each status and body in order. Read-only and free of side effects, so it is always safe to retry; counts as one request against the rate limit. An optional Idempotency-Key is accepted and echoed back.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"}}}},"responses":{"200":{"description":"Results in request order.","headers":{"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"Deprecation":{"$ref":"#/components/headers/Deprecation"},"Sunset":{"$ref":"#/components/headers/Sunset"},"Idempotency-Key":{"$ref":"#/components/headers/Idempotency-Key"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/InvalidToken"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"agentOAuth":{"type":"oauth2","description":"Optional. Identifies the agent and raises the rate limit to 600 requests per minute. Dynamic client registration and anonymous agent registration are described at https://justidea.agency/auth.md.","flows":{"authorizationCode":{"authorizationUrl":"https://justidea.agency/oauth/authorize/","tokenUrl":"https://justidea.agency/oauth/token/","refreshUrl":"https://justidea.agency/oauth/token/","scopes":{"site:read":"Read public content of justidea.agency (REST API and MCP server)."}}}}},"parameters":{"Query":{"name":"q","in":"query","required":true,"description":"What to look for, in Polish or English, e.g. \"sklep prestashop cena\", \"SEO audit\", \"kampanie Google Ads\".","schema":{"type":"string","minLength":1,"maxLength":200}},"Lang":{"name":"lang","in":"query","required":false,"description":"Only pages in this language.","schema":{"type":"string","enum":["pl","en"]}},"OfferLang":{"name":"lang","in":"query","required":false,"description":"Language of the offer: \"pl\" (prices in PLN, default) or \"en\" (prices in EUR for clients outside Poland).","schema":{"type":"string","enum":["pl","en"],"default":"pl"}},"PageType":{"name":"type","in":"query","required":false,"description":"Only pages of this kind.","schema":{"type":"string","enum":["services_index","service_area","service","city_page","pricing","case_studies","event","blog","company"]}},"SearchLimit":{"name":"limit","in":"query","required":false,"description":"Maximum number of results.","schema":{"type":"integer","minimum":1,"maximum":25,"default":8}},"PageLimit":{"name":"limit","in":"query","required":false,"description":"Maximum number of pages in one response.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"Cursor":{"name":"cursor","in":"query","required":false,"description":"Opaque cursor: next_cursor from the previous response. Omit for the first page.","schema":{"type":"string","maxLength":64}},"Url":{"name":"url","in":"query","required":true,"description":"Page URL on justidea.agency, a path starting with \"/\" or the .md address, e.g. \"/pl/uslugi/sklepy-internetowe/\".","schema":{"type":"string","minLength":1,"maxLength":500}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional client-chosen key (1 to 255 visible ASCII characters), echoed back. The batch has no side effects, so a retry with or without the key is always safe.","schema":{"type":"string","minLength":1,"maxLength":255}}},"headers":{"RateLimit-Policy":{"description":"Quota policy (IETF RateLimit header fields): \"ip\";q=120;w=60 without a token, \"agent\";q=600;w=60 with one.","schema":{"type":"string"}},"RateLimit":{"description":"Remaining quota (IETF RateLimit header fields). Sent with 429, where it is 0.","schema":{"type":"string"}},"X-RateLimit-Limit":{"description":"Requests allowed per 60-second window.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the window. Sent with 429, where it is 0.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"Link":{"description":"RFC 8288 link to the next page: <url>; rel=\"next\". Absent on the last page.","schema":{"type":"string"}},"Idempotency-Key":{"description":"The Idempotency-Key sent with the request, echoed back.","schema":{"type":"string"}},"Deprecation":{"description":"Present only once this endpoint or API version is deprecated: the date the deprecation took effect (RFC 9745). Absent on every endpoint today.","schema":{"type":"string"}},"Sunset":{"description":"Present only once a removal date is set (RFC 8594): the HTTP-date after which the endpoint stops answering, at least 90 days after Deprecation first appeared.","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"A parameter or the request body is invalid (code invalid-parameter or invalid-body).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unauthorized":{"description":"A bearer token is required (code unauthorized).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=\"https://justidea.agency/.well-known/oauth-protected-resource\", scope=\"site:read\"","schema":{"type":"string"}}}},"InvalidToken":{"description":"The bearer token is invalid or expired (code invalid-token). Call without a token or get a new one.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"WWW-Authenticate":{"description":"Bearer resource_metadata=\"https://justidea.agency/.well-known/oauth-protected-resource\", scope=\"site:read\", error=\"invalid_token\", error_description=\"The access token is invalid or expired\"","schema":{"type":"string"}}}},"NotFound":{"description":"No such public page or endpoint (code not-found).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"PayloadTooLarge":{"description":"The request body is too large (code payload-too-large).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"UnsupportedMediaType":{"description":"The request body is not JSON (code unsupported-media-type).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"TooManyRequests":{"description":"Rate limit exceeded (code rate-limited). Wait Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"}}},"InternalError":{"description":"Unexpected error (code internal-error). Retry later.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unavailable":{"description":"Site data is temporarily unavailable (code unavailable). Wait Retry-After seconds.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}},"schemas":{"Problem":{"type":"object","description":"Error in RFC 9457 format.","required":["type","title","status","code"],"properties":{"type":{"type":"string","format":"uri","description":"Link to the description of this error in /api.md."},"title":{"type":"string","description":"Short summary of the error type."},"status":{"type":"integer","description":"HTTP status code."},"detail":{"type":"string","description":"What went wrong in this request and how to fix it."},"instance":{"type":"string","description":"Path of the request that failed."},"code":{"type":"string","enum":["invalid-parameter","invalid-body","unsupported-media-type","payload-too-large","unauthorized","invalid-token","not-found","method-not-allowed","rate-limited","unavailable","internal-error"],"description":"Machine-readable error code."}}},"PageSummary":{"type":"object","required":["title","url","markdownUrl","type","lang"],"properties":{"title":{"type":"string"},"url":{"type":"string","format":"uri","description":"Canonical URL of the page."},"markdownUrl":{"type":"string","format":"uri","description":"The same page as Markdown."},"description":{"type":"string","description":"Meta description of the page."},"type":{"type":"string","enum":["services_index","service_area","service","city_page","pricing","case_studies","event","blog","company"]},"lang":{"type":"string","enum":["pl","en"]},"matchingSections":{"type":"array","items":{"type":"string"},"description":"Search only: section headings that matched the query."}}},"SearchResults":{"type":"object","required":["query","data"],"properties":{"query":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PageSummary"}},"note":{"type":"string"}}},"PageList":{"type":"object","required":["data","total","limit","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PageSummary"}},"total":{"type":"integer","description":"Number of pages matching the filters."},"limit":{"type":"integer"},"next_cursor":{"type":["string","null"],"description":"Pass as cursor to get the next page; null on the last page."}}},"PageContent":{"type":"object","required":["url","markdownUrl","markdown","truncated"],"properties":{"url":{"type":"string","format":"uri"},"markdownUrl":{"type":"string","format":"uri"},"title":{"type":"string"},"lang":{"type":"string","enum":["pl","en"]},"type":{"type":"string","enum":["services_index","service_area","service","city_page","pricing","case_studies","event","blog","company"]},"markdown":{"type":"string","description":"Page content as Markdown."},"truncated":{"type":"boolean","description":"True when the page was longer than 80000 characters and was cut."}}},"Services":{"type":"object","required":["language","prices_note","pricing","services"],"properties":{"language":{"type":"string","enum":["pl","en"]},"prices_note":{"type":"string"},"pricing":{"type":"array","items":{"type":"object","required":["name","from_price","currency","pricing_page"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"from_price":{"type":["number","null"],"description":"Net starting price as published; null = quoted individually."},"currency":{"type":"string","description":"ISO 4217 code."},"pricing_page":{"type":"string","format":"uri","description":"Page where this price is published."},"packages":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"from_price":{"type":["number","null"]},"currency":{"type":"string"}}}}}}},"services":{"type":"array","items":{"type":"object","required":["title","url","kind"],"properties":{"title":{"type":"string"},"url":{"type":"string","format":"uri"},"kind":{"type":"string"},"description":{"type":"string"}}}},"nextStep":{"type":"string"}}},"ContactOptions":{"type":"object","required":["company","email","phone","contactForm","languages"],"properties":{"company":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"contactForm":{"description":"Contact page: one URL when lang is given, otherwise a map from language to URL.","oneOf":[{"type":"string","format":"uri"},{"type":"object","additionalProperties":{"type":"string","format":"uri"}}]},"privacyPolicy":{"description":"Privacy policy: one URL when lang is given, otherwise a map from language to URL.","oneOf":[{"type":"string","format":"uri"},{"type":"object","additionalProperties":{"type":"string","format":"uri"}}]},"languages":{"type":"array","items":{"type":"string"}},"note":{"type":"string"}}},"AgentIdentity":{"type":"object","required":["authenticated","sub","scope","resource","rateLimit"],"properties":{"authenticated":{"type":"boolean","const":true},"sub":{"type":"string","description":"Agent identifier from the token."},"scope":{"type":"string"},"resource":{"type":"string","format":"uri"},"rateLimit":{"type":"object","required":["policy","limit","windowSeconds"],"properties":{"policy":{"type":"string"},"limit":{"type":"integer"},"windowSeconds":{"type":"integer"}}}}},"Health":{"type":"object","required":["ok","version"],"properties":{"ok":{"type":"boolean"},"version":{"type":"string"},"pages":{"type":"integer"},"languages":{"type":"array","items":{"type":"string"}},"error":{"type":"string"}}},"ApiRoot":{"type":"object","required":["name","version","apiVersion","openapi","endpoints"],"properties":{"name":{"type":"string"},"version":{"type":"string"},"apiVersion":{"type":"string"},"description":{"type":"string"},"openapi":{"type":"string","format":"uri"},"openapiYaml":{"type":"string","format":"uri"},"documentation":{"type":"string","format":"uri"},"mcp":{"type":"string","format":"uri"},"mcpRegistry":{"type":"string","format":"uri"},"authentication":{"type":"string"},"endpoints":{"type":"object","additionalProperties":{"type":"string"}}}},"BatchRequest":{"type":"object","required":["requests"],"properties":{"requests":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"object","required":["path"],"properties":{"id":{"type":["string","integer"],"description":"Echoed back in the result; defaults to the position."},"method":{"type":"string","enum":["GET"],"default":"GET"},"path":{"type":"string","description":"Path with query string, e.g. \"/api/v1/search?q=prestashop\".","pattern":"^/api/v1"}}}}}},"BatchResponse":{"type":"object","required":["responses"],"properties":{"responses":{"type":"array","items":{"type":"object","required":["id","status","body"],"properties":{"id":{"type":["string","integer"]},"status":{"type":"integer"},"body":{"description":"The body the same GET would return: its success schema or Problem.","type":"object"}}}}}}}}}