{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"4OVER4.COM Agent API","version":"1.2.0","summary":"Catalog, live pricing, knowledge and the signed-in account of 4OVER4.COM online printing, for AI agents.","description":"The public machine surface of 4OVER4.COM. Agents find products, price them live, read the help and, after the customer signs in with 4OVER4 (OAuth 2.1 with PKCE), read that customer's own orders, profile, coins and cart. Ordering, artwork upload and payment always happen on 4over4.com.\n\nErrors: every HTTP-level error under /appsapi answers application/problem+json (RFC 9457) with type, title, status, detail, a stable code and a hint. MCP and A2A errors inside a JSON-RPC body stay JSON-RPC errors; OAuth endpoints answer RFC 6749 errors. An unknown /appsapi path answers 404 problem+json.\n\nRate limits: rate-limited operations send RateLimit-Policy and RateLimit (IETF draft-ietf-httpapi-ratelimit-headers), and every 429 sends Retry-After. Windows are 60 seconds.\n\nVersioning: there are no versioned paths. This document's info.version follows semantic versioning; a breaking change goes through the deprecation policy.\n\nDeprecation policy: An operation or field that will be removed is first marked deprecated in the OpenAPI description at https://www.4over4.com/openapi.json. From that day its responses carry a Deprecation header (RFC 9745) with the date it was deprecated, a Sunset header (RFC 8594) with the date after which it may stop working, at least 90 days later, and a Link header with rel=\"deprecation\" to the notice. Nothing is removed before its Sunset date. Additions (new operations, new optional fields, new error codes) come without notice, so ignore fields you do not know.","contact":{"name":"4OVER4.COM support","url":"https://www.4over4.com/company/contact","email":"support@4over4.com"},"termsOfService":"https://www.4over4.com/company/terms-and-conditions"},"externalDocs":{"description":"How to connect an assistant, the error codes and the deprecation policy.","url":"https://www.4over4.com/ai-mode/connect#developers"},"x-service-info":{"categories":["printing","e-commerce","custom-products"]},"servers":[{"url":"https://www.4over4.com"}],"tags":[{"name":"MCP","description":"The Model Context Protocol server (Streamable HTTP, JSON responses, no SSE)."},{"name":"A2A","description":"The Agent2Agent 1.0 endpoint."},{"name":"UCP","description":"Universal Commerce Protocol 2026-04-08, as MCP tools, and the cart hand-off page."},{"name":"Pricing","description":"Live price quotes."},{"name":"OAuth","description":"Sign in with 4OVER4, for the account tools."},{"name":"Checkout","description":"The human checkout on 4over4.com."},{"name":"Discovery","description":"This document."}],"paths":{"/appsapi/mcp":{"post":{"operationId":"mcp","summary":"Call the MCP server: one JSON-RPC 2.0 request, or a batch of up to 10.","description":"MCP over Streamable HTTP with JSON responses. Tools: list_categories, show_products, find_similar_products, compare_products, recommend, marketing_kit, configure_product, price_breaks, delivery_by_zip, print_calculator, search_design_templates, daily_deals, search_knowledge, search_content, talk_to_human, get_my_orders, get_order_details, cancel_order, get_my_profile, get_my_coins, loyalty_tasks, get_cart. UCP tools: search_catalog, lookup_catalog, get_product, create_cart, get_cart, update_cart, cancel_cart, create_checkout, get_checkout, update_checkout, complete_checkout, cancel_checkout, get_order. Account tools need the oauth2 scope \"account\"; without it they answer a sign-in challenge. DELETE ends a session and always answers 200 with no body. Rate limits: \"mcp\" 120 per 60s, \"mcp-ip\" 1200 per 60s, \"mcp-knowledge\" 120 per 60s, \"mcp-knowledge-ip\" 1200 per 60s.","tags":["MCP","UCP"],"security":[{},{"oauth2":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRequestBody"}}}},"responses":{"200":{"description":"The JSON-RPC response, or an array for a batch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpResponseBody"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"202":{"description":"Only notifications were sent; no body.","headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"400":{"description":"A parse error, an invalid request or a protocol header mismatch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"401":{"description":"Sign-in is needed for this tool. WWW-Authenticate names the protected resource metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}},"headers":{"WWW-Authenticate":{"description":"The Bearer challenge.","schema":{"type":"string"}}}},"404":{"description":"The method does not exist (modern protocol versions).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}},"503":{"description":"A dependency is unavailable for a moment. Retry after Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}},"headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}},"get":{"operationId":"mcpGet","summary":"Not allowed: this endpoint answers POST, DELETE, OPTIONS.","description":"Not allowed: this endpoint answers POST, DELETE, OPTIONS.","tags":["MCP"],"responses":{"405":{"description":"Method not allowed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"description":"The allowed methods.","schema":{"type":"string","example":"POST, DELETE, OPTIONS"}}}}}}},"/appsapi/a2a":{"post":{"operationId":"a2a","summary":"Call the A2A agent: one JSON-RPC 2.0 request.","description":"A2A 1.0 over JSON-RPC. Send the A2A-Version header. SendMessage asks Wally; a data part with a skill id runs that skill. Skills: ask_wally, list_categories, show_products, find_similar_products, compare_products, recommend, marketing_kit, configure_product, price_breaks, delivery_by_zip, print_calculator, daily_deals, search_knowledge, search_content, talk_to_human, get_my_orders, get_order_details, get_my_profile, get_my_coins, get_cart, loyalty_tasks, search_catalog, lookup_catalog, get_product. Rate limits: \"a2a\" 20 per 60s.","tags":["A2A"],"security":[{},{"oauth2":["account"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"}}}},"responses":{"200":{"description":"The JSON-RPC response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"400":{"description":"A parse error, an invalid request or an unsupported A2A version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"401":{"description":"The access token is not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}},"headers":{"WWW-Authenticate":{"description":"The Bearer challenge.","schema":{"type":"string"}}}},"413":{"description":"The request is larger than 64 KB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}},"503":{"description":"Wally could not answer this time. Retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcError"}}}}}},"get":{"operationId":"a2aGet","summary":"Not allowed: this endpoint answers POST, OPTIONS.","description":"Not allowed: this endpoint answers POST, OPTIONS.","tags":["A2A"],"responses":{"405":{"description":"Method not allowed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"Allow":{"description":"The allowed methods.","schema":{"type":"string","example":"POST, OPTIONS"}}}}}}},"/.well-known/agent-card.json":{"get":{"operationId":"agentCard","summary":"The A2A agent card.","description":"The A2A agent card.","tags":["A2A"],"responses":{"200":{"description":"The agent card.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCard"}}}}}}},"/appsapi/a2a/agent-card.json":{"get":{"operationId":"agentCard2","summary":"The A2A agent card, under /appsapi.","description":"The A2A agent card, under /appsapi.","tags":["A2A"],"responses":{"200":{"description":"The agent card.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCard"}}}}}}},"/appsapi/products/ipc":{"post":{"operationId":"priceQuote","summary":"Live price quote for a product configuration (free to call).","description":"Answers the configuration surface (sizes, quantities, papers, options, turnaround) and the exact price for the configuration sent. Available sizes and options change with the selected size. Rate limits: \"ipc\" 90 per 60s.","tags":["Pricing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpcRequest"}}}},"responses":{"200":{"description":"The configuration surface and the exact price.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpcEnvelope"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"404":{"description":"No configurator for this product.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/IpcProblem"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"410":{"description":"The product is no longer sold.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/IpcProblem"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}}},"/appsapi/ucp/handoff/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The checkout id from a UCP checkout's continue_url."}],"get":{"operationId":"ucpHandoffPage","summary":"The cart page a person opens from a UCP continue_url.","description":"The cart page a person opens from a UCP continue_url.","tags":["UCP"],"responses":{"200":{"description":"The cart page.","content":{"text/html":{"schema":{"$ref":"#/components/schemas/HtmlPage"}}}},"303":{"description":"The checkout is unknown, expired or already added: opens where it goes next.","headers":{"Location":{"description":"Where to go.","schema":{"type":"string"}}}}}},"post":{"operationId":"ucpHandoff","summary":"The person adds the items to their 4OVER4 cart (the page's own form).","description":"The person adds the items to their 4OVER4 cart (the page's own form). Rate limits: \"ucp-handoff\" 30 per 60s.","tags":["UCP"],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/HandoffForm"}}}},"responses":{"303":{"description":"Opens the 4over4.com cart.","headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Location":{"description":"The cart.","schema":{"type":"string"}}}},"403":{"description":"The form did not come from the cart page.","content":{"text/html":{"schema":{"$ref":"#/components/schemas/HtmlPage"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"429":{"description":"Rate limited.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"authServerMetadata","summary":"OAuth authorization server metadata.","description":"OAuth authorization server metadata.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthServerMetadata"}}}}}}},"/.well-known/oauth-authorization-server/appsapi/oauth":{"get":{"operationId":"authServerMetadata2","summary":"OAuth authorization server metadata.","description":"OAuth authorization server metadata.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthServerMetadata"}}}}}}},"/appsapi/oauth/.well-known/oauth-authorization-server":{"get":{"operationId":"authServerMetadata3","summary":"OAuth authorization server metadata.","description":"OAuth authorization server metadata.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthServerMetadata"}}}}}}},"/appsapi/oauth/.well-known/openid-configuration":{"get":{"operationId":"authServerMetadata4","summary":"OAuth authorization server metadata.","description":"OAuth authorization server metadata.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthServerMetadata"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"protectedResourceMetadata","summary":"Protected resource metadata of the MCP server.","description":"Protected resource metadata of the MCP server.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}},"/.well-known/oauth-protected-resource/appsapi/mcp":{"get":{"operationId":"protectedResourceMetadata2","summary":"Protected resource metadata of the MCP server.","description":"Protected resource metadata of the MCP server.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}},"/appsapi/oauth/protected-resource":{"get":{"operationId":"protectedResourceMetadata3","summary":"Protected resource metadata of the MCP server.","description":"Protected resource metadata of the MCP server.","tags":["OAuth"],"responses":{"200":{"description":"The metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}},"/appsapi/oauth/authorize":{"get":{"operationId":"authorize","summary":"The sign-in page (authorization code with PKCE S256).","description":"The sign-in page (authorization code with PKCE S256). Rate limits: \"oauth-authorize\" 30 per 60s.","tags":["OAuth"],"responses":{"200":{"description":"The sign-in page, or a page that names what is wrong with the request.","content":{"text/html":{"schema":{"$ref":"#/components/schemas/HtmlPage"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}},"post":{"operationId":"authorizeSignIn","summary":"The sign-in page's own form.","description":"The sign-in page's own form. Rate limits: \"oauth\" 20 per 60s, \"oauth-account\" 20 per 60s.","tags":["OAuth"],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/SignInForm"}}}},"responses":{"200":{"description":"The sign-in page again, with what went wrong.","content":{"text/html":{"schema":{"$ref":"#/components/schemas/HtmlPage"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}},"302":{"description":"Back to the client's redirect_uri with code, state and iss.","headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Location":{"description":"The redirect.","schema":{"type":"string"}}}}}}},"/appsapi/oauth/token":{"post":{"operationId":"token","summary":"Exchange an authorization code or a refresh token.","description":"Exchange an authorization code or a refresh token. Rate limits: \"oauth-token\" 60 per 60s.","tags":["OAuth"],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"The tokens.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"400":{"description":"invalid_grant, invalid_request or unsupported_grant_type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"401":{"description":"invalid_client.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"429":{"description":"slow_down.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}},"503":{"description":"temporarily_unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}}},"/appsapi/oauth/revoke":{"post":{"operationId":"revoke","summary":"Revoke a token (RFC 7009).","description":"Revoke a token (RFC 7009). Rate limits: \"oauth-revoke\" 60 per 60s.","tags":["OAuth"],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/RevokeRequest"}}}},"responses":{"200":{"description":"Revoked, or the token was not valid; no body.","headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"400":{"description":"invalid_request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"401":{"description":"invalid_client.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"429":{"description":"slow_down.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}},"503":{"description":"temporarily_unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}}},"/appsapi/oauth/register":{"post":{"operationId":"register","summary":"Dynamic client registration (RFC 7591).","description":"Dynamic client registration (RFC 7591). Rate limits: \"oauth-register\" 30 per 60s.","tags":["OAuth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}}},"responses":{"201":{"description":"The registered client.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"400":{"description":"invalid_client_metadata or invalid_redirect_uri.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"}}},"429":{"description":"slow_down.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}},"headers":{"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimit-Policy"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}}}}}},"/checkout":{"get":{"operationId":"checkoutSession","summary":"Human checkout for a configured cart. The payment step always happens here.","description":"Human checkout for a configured cart. The payment step always happens here.","tags":["Checkout"],"responses":{"200":{"description":"The checkout page.","content":{"text/html":{"schema":{"$ref":"#/components/schemas/HtmlPage"}}}}},"x-served-by":"labs","x-payment-info":{"intent":"session","method":"card","amount":"0.00","currency":"USD","description":"Amount equals the live quote total for the configured cart; charged at checkout on 4over4.com, never by the agent."}}},"/openapi.json":{"get":{"operationId":"openapi","summary":"This OpenAPI document.","description":"This OpenAPI document.","tags":["Discovery"],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenApiDocument"}}}}}}}},"components":{"schemas":{"Problem":{"type":"object","properties":{"type":{"type":"string","description":"A URI for the error kind: https://www.4over4.com/ai-mode/connect#error-<code>."},"title":{"type":"string","description":"The HTTP status text."},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The HTTP status code."},"detail":{"type":"string","description":"What went wrong with this request."},"code":{"type":"string","enum":["invalid_request","unauthorized","forbidden","not_found","method_not_allowed","product_retired","payload_too_large","rate_limited","upstream_unavailable","not_configured"],"description":"A stable, machine-readable error code."},"hint":{"type":"string","description":"A short hint on how to resolve it."}},"required":["type","title","status","detail","code","hint"],"additionalProperties":{},"description":"An RFC 9457 problem details object. Every HTTP-level error under /appsapi answers in this shape, except the JSON-RPC errors of MCP and A2A and the OAuth errors, which keep the shapes their specifications define."},"JsonRpcRequest":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","number","null"]},"method":{"type":"string"},"params":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["jsonrpc","method"],"additionalProperties":{}},"JsonRpcError":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","number","null"]},"error":{"type":"object","properties":{"code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message":{"type":"string"},"data":{}},"required":["code","message"],"additionalProperties":{}}},"required":["jsonrpc","id","error"],"additionalProperties":{}},"JsonRpcResult":{"type":"object","properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"type":["string","number","null"]},"result":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["jsonrpc","id","result"],"additionalProperties":{}},"JsonRpcResponse":{"anyOf":[{"$ref":"#/components/schemas/JsonRpcResult"},{"$ref":"#/components/schemas/JsonRpcError"}]},"McpRequestBody":{"anyOf":[{"$ref":"#/components/schemas/JsonRpcRequest"},{"minItems":1,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/JsonRpcRequest"}}]},"McpResponseBody":{"anyOf":[{"$ref":"#/components/schemas/JsonRpcResponse"},{"type":"array","items":{"$ref":"#/components/schemas/JsonRpcResponse"}}]},"IpcRequest":{"type":"object","properties":{"productGroupName":{"description":"The product, by its configurator name or slug.","type":"string"},"requestedProductGroupName":{"type":"string"},"slug":{"type":"string"}},"additionalProperties":{},"description":"A product configuration, as the 4OVER4 configurator sends it. Send the product, then any chosen size, quantity, paper, options and turnaround."},"IpcEnvelope":{"type":"object","properties":{"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"message":{"type":"string"},"data":{"description":"The configuration surface and the price.","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"additionalProperties":{}},"IpcProblem":{"type":"object","properties":{"type":{"type":"string","description":"A URI for the error kind: https://www.4over4.com/ai-mode/connect#error-<code>."},"title":{"type":"string","description":"The HTTP status text."},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The HTTP status code."},"detail":{"type":"string","description":"What went wrong with this request."},"code":{"type":"string","enum":["invalid_request","unauthorized","forbidden","not_found","method_not_allowed","product_retired","payload_too_large","rate_limited","upstream_unavailable","not_configured"],"description":"A stable, machine-readable error code."},"hint":{"type":"string","description":"A short hint on how to resolve it."},"message":{"type":"string","description":"The same text as detail, kept for the configurator."},"data":{"type":"null"}},"required":["type","title","status","detail","code","hint","message","data"],"additionalProperties":{}},"AgentCard":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"supportedInterfaces":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"protocolBinding":{"type":"string"},"protocolVersion":{"type":"string"}},"required":["url","protocolBinding","protocolVersion"],"additionalProperties":{}}},"version":{"type":"string"},"skills":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}},"required":["id","name","description"],"additionalProperties":{}}}},"required":["name","description","supportedInterfaces","version","skills"],"additionalProperties":{},"description":"An A2A 1.0 agent card."},"AuthServerMetadata":{"type":"object","properties":{"issuer":{"type":"string"},"authorization_endpoint":{"type":"string"},"token_endpoint":{"type":"string"},"revocation_endpoint":{"type":"string"},"registration_endpoint":{"type":"string"},"scopes_supported":{"type":"array","items":{"type":"string"}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}}},"required":["issuer","authorization_endpoint","token_endpoint","revocation_endpoint","registration_endpoint","scopes_supported","code_challenge_methods_supported"],"additionalProperties":{},"description":"RFC 8414 authorization server metadata."},"ProtectedResourceMetadata":{"type":"object","properties":{"resource":{"type":"string"},"authorization_servers":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}}},"required":["resource","authorization_servers","scopes_supported"],"additionalProperties":{},"description":"RFC 9728 protected resource metadata of the MCP server."},"TokenRequest":{"type":"object","properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"code":{"type":"string"},"redirect_uri":{"type":"string"},"code_verifier":{"type":"string"},"refresh_token":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"resource":{"type":"string"}},"required":["grant_type"],"additionalProperties":false},"TokenResponse":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string","const":"Bearer"},"expires_in":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"refresh_token":{"type":"string"},"scope":{"type":"string"}},"required":["access_token","token_type","expires_in","refresh_token","scope"],"additionalProperties":{}},"RevokeRequest":{"type":"object","properties":{"token":{"type":"string"},"token_type_hint":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"}},"required":["token"],"additionalProperties":false},"OAuthError":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error"],"additionalProperties":{},"description":"An RFC 6749 error, the shape OAuth clients expect."},"RegisterRequest":{"type":"object","properties":{"redirect_uris":{"minItems":1,"type":"array","items":{"type":"string"}},"client_name":{"type":"string"},"token_endpoint_auth_method":{"type":"string","enum":["none","client_secret_post","client_secret_basic"]}},"required":["redirect_uris"],"additionalProperties":{}},"RegisterResponse":{"type":"object","properties":{"client_id":{"type":"string"},"client_id_issued_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_secret":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"}},"required":["client_id","client_id_issued_at","redirect_uris","token_endpoint_auth_method"],"additionalProperties":{}},"SignInForm":{"type":"object","properties":{"username":{"type":"string"},"password":{"type":"string"},"client_id":{"type":"string"},"redirect_uri":{"type":"string"},"code_challenge":{"type":"string"},"state":{"type":"string"},"resource":{"type":"string"}},"required":["username","password","client_id","redirect_uri","code_challenge"],"additionalProperties":{}},"HandoffForm":{"type":"object","properties":{"csrf":{"type":"string"}},"required":["csrf"],"additionalProperties":false},"HtmlPage":{"type":"string","description":"An HTML page for a person."},"OpenApiDocument":{"type":"object","properties":{"openapi":{"type":"string"},"info":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"paths":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["openapi","info","paths"],"additionalProperties":{}}},"headers":{"RateLimit":{"description":"The budget left in each policy, as `\"<policy>\";r=<remaining>;t=<seconds to reset>` items (draft-ietf-httpapi-ratelimit-headers).","schema":{"type":"string","example":"\"ipc\";r=89;t=60"}},"RateLimit-Policy":{"description":"Each policy, as `\"<policy>\";q=<quota>;w=<window seconds>` items (draft-ietf-httpapi-ratelimit-headers).","schema":{"type":"string","example":"\"ipc\";q=90;w=60"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}},"Deprecation":{"description":"RFC 9745: when this operation was deprecated, as @<unix seconds>. Sent only on deprecated operations.","schema":{"type":"string","example":"@1798761600"}},"Sunset":{"description":"RFC 8594: the HTTP date after which a deprecated operation may stop working. Sent only on deprecated operations.","schema":{"type":"string","example":"Sat, 01 May 2027 00:00:00 GMT"}}},"securitySchemes":{"oauth2":{"type":"oauth2","description":"Sign in with 4OVER4. Needed only for the account tools.","flows":{"authorizationCode":{"authorizationUrl":"https://www.4over4.com/appsapi/oauth/authorize","tokenUrl":"https://www.4over4.com/appsapi/oauth/token","refreshUrl":"https://www.4over4.com/appsapi/oauth/token","scopes":{"account":"Read your own 4OVER4 orders, profile, coins and cart.","offline_access":"Stay signed in with a refresh token."}}}}}}}