{"kind":"service-guide","reviewedAt":"2026-09-27","documentation":"https://angelsprint.com/customer-service#ai-agents","apiReference":"https://angelsprint.com/api/agent/openapi.json","connection":{"endpoint":"https://angelsprint.com/api/mcp","transport":"JSON-RPC over HTTP POST","protocolVersion":"2025-06-18","authentication":"none for public tools"},"approvalPolicy":"Orders are never charged automatically. An agent can only prepare a draft; a human operator must open the approval link, review the cart and pay via Stripe Checkout.","pricingPolicy":"Every price is recomputed on the server from the product configuration — at quote, at draft, and again before checkout. A price sent by a client is ignored. An itemId preserves selections, not a locked price; a changed catalogue can require a new quote and draft.","currentCapabilities":[{"method":"GET","path":"/api/agent/products","operationId":"searchProducts","tool":"search_products","summary":"Search or list the catalogue. Every word must match; returns slugs, entry prices and the category counts."},{"method":"GET","path":"/api/agent/products/{slug}","operationId":"getProduct","tool":"get_product","summary":"One product's whole option surface: stocks and finishes with price deltas, the quantity ladder, turnaround speeds, size limits."},{"method":"POST","path":"/api/agent/quote","operationId":"getQuote","tool":"get_quote","summary":"Exact price for one configured product, plus an itemId that pins those selections for the order."},{"method":"POST","path":"/api/agent/orders","operationId":"createOrder","tool":"create_order","summary":"Prepare a draft and get the approval link for the human operator. Charges nothing and writes no order."},{"method":"GET","path":"/api/agent/orders/{draft_id}","operationId":"checkOrder","tool":"check_order","summary":"Check draft validity and payment: awaiting_approval, paid or expired. No proof, production, shipment or delivery tracking."}],"privateWork":{"version":"2026-09-27","endpoint":"https://angelsprint.com/api/agent/work","mcp":"https://angelsprint.com/api/agent/work/mcp","account":"https://angelsprint.com/account/work","authentication":"Use Authorization: Bearer <current Supabase customer access token>. The server verifies the user on every request, including MCP initialize/tools/list. The shop account uses its verified same-origin session. A draft ID, proof token, email address or service-role key is not customer authentication. No delegated grants or OAuth connector are issued by this endpoint.","ownership":"Only jobs explicitly linked through orders.user_id or, for jobs without an order, crm_customers.user_id are accessible. Conflicting account links are denied. No email matching. Unlinked guest purchases are not automatically visible.","privacy":"Do not paste access tokens into prompts, URLs, support questions, source control or shared logs. Supply them through your client's protected Authorization header; reconnect after expiry using your trusted account integration. This guide does not expose or mint tokens.","capabilities":[{"tool":"list_my_orders","method":"GET","path":"/api/agent/work","detail":"Newest account-owned work records, including enquiries; limit 1–50, default 25. coverage says whether the bounded window is complete."},{"tool":"get_work","method":"GET","path":"/api/agent/work/{workId}","detail":"Independent money, latest proof, artwork and recorded lifecycle facts; next action with honest unknown/unimplemented states."},{"tool":"list_work_files","method":"GET","path":"/api/agent/work/{workId}/files","detail":"Customer-supplied file metadata only. No download URL, upload capability or byte/preflight validation."},{"tool":"list_work_events","method":"GET","path":"/api/agent/work/{workId}/events","detail":"Latest 50 allowlisted recorded lifecycle events for this work, with coverage. Not the full CRM inbox."},{"tool":"list_work_questions","method":"GET","path":"/api/agent/work/{workId}/support","detail":"This work's private factual-agent conversation; limit 1–50. Email and general account messages remain separate."},{"tool":"ask_work_question","method":"POST","path":"/api/agent/work/{workId}/support","detail":"Save question (1–2000 characters) and deterministic answer from verified records. Required clientRequestId UUID: reuse on retry; different content with the same key returns409. Does not execute custom requests or send external messages."}],"boundaries":["The canonical identifier is job:UUID returned by list_my_orders, not an order number or signed draft ID. A linked orderId is a separate field.","Read coverage before using values. Missing or truncated money/proof records stay unknown. List windows are bounded, not exhaustive pagination or account-wide totals.","Ownership is rechecked after scoped reads. Facts are a timestamped, rechecked snapshot across sources, not one serializable database transaction.","Recorded shop phases, producedAt and deliveredAt are records, not machine telemetry, carrier scans or independent customer receipt. No full autonomous fulfillment is claimed.","No file bytes, upload intents, approval links, proof decisions, payments or production controls are exposed. Existing Blob storage may be public; authenticated metadata does not make legacy files private.","The factual support agent answers from a status snapshot without an external model. It does not contact staff, merge email threads or promise changes. A custom request needs the existing order conversation."],"limits":{"bodyBytes":8192,"batchMessages":1,"requestsPerMinutePerUser":60,"questionsPerMinutePerUser":10,"authenticationAttemptsPerMinutePerIp":120,"scope":"Best effort in memory per server instance; not a fleet-wide quota."},"errors":{"unauthorized":"401: authenticate again; do not substitute a draft or proof token.","work_not_found":"404: no work is disclosed outside this account's explicit links.","idempotency_conflict":"409: use the original request for a retry, or a new UUID for a new question.","support_unavailable":"503: no saved answer is confirmed; retry the same clientRequestId. Read-only work endpoints remain separate.","unavailable":"503: facts or identity could not be verified; do not infer zero or success.","rate_limited":"429 over REST; MCP tools may return isError:true. Back off."},"example":{"connection":{"url":"https://angelsprint.com/api/agent/work/mcp","transport":"HTTP JSON-RPC POST","header":"Authorization: Bearer <customer access token from your trusted session integration>"},"list":{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"list_my_orders","arguments":{"limit":10}}},"question":{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"ask_work_question","arguments":{"workId":"job:<UUID returned by list_my_orders>","question":"What is the recorded status and next step?","clientRequestId":"<new UUID; preserve for retries>"}}}}},"currentBoundaries":["Available now: catalogue search, product options, exact configuration pricing, signed approval drafts and payment-status lookup over MCP or REST. No API key is required for these public operations.","The customer reviews the purchase and pays. Draft creation does not place a paid order, send an email, upload artwork or start production. Return the approval link to the customer in your own application.","The public MCP does not expose an order-message thread, customer file library, print-file preflight, proof approval, production controls, courier tracking or a delivery-completion tool. Use the account and order-specific links for supported customer actions.","The workflow below covers the complete customer journey and identifies each current interface. It is not a claim that every stage already runs autonomously. Customer approval and payment remain separate from the shop's goal of autonomous operations."],"workflow":[{"id":"brief","title":"Understand the job","via":"Your AI assistant · Customer","detail":"Collect the product or intended use, finished dimensions, quantity, material/finish, artwork versions, required date and pickup or delivery ZIP. An event date is a requirement, not a confirmed delivery promise.","agentAction":"Ask for missing details. Read the catalogue and this guide; do not invent a product, option or price.","handoff":"For custom fabrication, installation or a non-catalogue specification, use the contact form or email for a shop quote."},{"id":"configure","title":"Find, configure and price","via":"search_products → get_product → get_quote","detail":"Read the actual quantity ladder, size limits, options and turnaround names. API dimensions are inches; prices are USD. quantity is pieces per print run; packages on a quote and qty on an order line mean repeated identical runs.","agentAction":"Show chosen, summary, adjustments, shippingStatus and the returned total. Preserve itemId for the draft. Quantity may be adjusted; an itemId preserves configuration, not a price guarantee.","handoff":"Use fulfillment: pickup for free shop collection, or delivery plus the destination ZIP. Delivery costs at least $50; an unknown quote is not a fixed $50 charge. Unknown shipping or a null total must be resolved before promising a final amount."},{"id":"files","title":"Collect the right artwork","via":"artwork[] references · Upload link · Account","detail":"A draft can reference up to 10 HTTPS artwork URLs (480 characters each). The API records references; it does not retrieve, inspect or certify their contents. The separate authenticated private-work API can read customer file metadata; it returns no file bytes or download capability.","agentAction":"Use only files the customer authorized. Identify the latest source, dimensions and intended sides. Keep shared links accessible to the intended recipient; do not publish customer artwork or capability tokens.","handoff":"Use the upload link supplied for that order or its signed-in account upload. Request the correct link if none was supplied; do not invent artwork/proof tokens."},{"id":"approval","title":"Prepare the purchase for review","via":"create_order → approval_url → Customer","detail":"Create the draft with an itemId per line, operator.email, fulfillment and any delivery ZIP. Save draft_id and expires_at privately. The signed draft normally expires after 7 days; signing prevents editing but does not encrypt its customer information.","agentAction":"Return approval_url, the exact configured summary, adjustments and next_step to the customer. No approval email is sent by create_order. Reuse the existing draft for follow-up instead of creating a new one for every status check.","handoff":"The customer opens the review page and pays through Stripe. The approval page can collect a missing delivery ZIP or switch to pickup; payment totals are checked again."},{"id":"payment","title":"Confirm payment independently","via":"check_order · Customer receipt","detail":"The public status tool reports awaiting_approval, paid or expired. Payment is separate from a proof decision and from physical production. A paid response confirms the payment lookup, not that a parcel is moving.","agentAction":"Read payment_lookup as well as status. If lookup is unavailable, report payment as unknown and retry later without initiating another payment. Keep draft_id separate from the actual order reference.","handoff":"If the customer paid but the result cannot be reconciled, use their receipt and order reference in an authenticated message or the existing email thread."},{"id":"proof","title":"Validate the file and approve the proof","via":"Artwork review · Order-specific proof link · Customer","detail":"Receiving a file checks neither print readiness nor customer approval. The shop's file review and the customer's visual approval are separate. A proof link lets the customer inspect the presented version and approve it or request changes.","agentAction":"Check the file checklist below, keep a clear revision record and explain unresolved issues. Never infer bleed, resolution, fonts or color accuracy from a successful upload. MCP has no preflight or proof-decision tool.","handoff":"The customer uses the supplied proof link. If the file or scope changes, obtain review of the new version. Production readiness must be verified from the applicable payment, file and proof records."},{"id":"production","title":"Follow the recorded production status","via":"Linked account order · Order email","detail":"A quote's production-day estimate is not machine telemetry. The current public agent API does not expose printing, cutting, finishing, quality checks, packaging or a production-completion event.","agentAction":"Keep the deadline and last confirmed update together. Do not turn payment success, a generated proof or a target date into a ready-for-pickup message.","handoff":"Check the linked account order where available, or continue the existing order conversation. Wait for an explicit readiness update before arranging collection."},{"id":"delivery","title":"Collect, receive and resolve issues","via":"Ready notice · Delivery information · Customer","detail":"For pickup, use the shop address and hours after readiness is confirmed. For delivery, use the shipping information actually supplied. The MCP payment-status endpoint does not return carrier tracking or proof of delivery.","agentAction":"Keep pickup and delivery distinct. A label, estimate or payment is not evidence of receipt. For damage or a production defect, gather the order reference, photos and the customer's description promptly.","handoff":"Follow the pickup/shipping and problems/reprints instructions on Customer Service. A completed order needs a confirmed outcome; do not mark it delivered because no further message arrived."}],"fileChecklist":["Identify the approved source and version, finished dimensions, orientation, sides/pages and intended product. Ask about any mismatch instead of silently resizing or replacing the file.","Confirm format and size against the specific upload form. Current shop upload routes accept PDF, PNG, JPG, WEBP, AI, EPS, DXF, DWG up to 25 MB; a draft's HTTPS reference is a different transport and does not validate those bytes.","Check artwork at the final print size: image resolution, legibility, bleed, trim and safe area. Requirements vary by product; do not apply one assumed bleed or DPI to every job.","Review embedded/outlined fonts, linked images, color spaces and any critical-color requirement. A screen preview or generated AI image does not certify the output on the chosen material.","For cutting work, confirm scale, dimensions and cut geometry with the job specification. Accepting a DXF/DWG upload does not prove that a machine can execute its toolpath.","Separate the received source, the customer-facing proof and the final production file. Keep file checks, approval of the exact version and actual production as distinct recorded outcomes."],"statuses":[{"status":"awaiting_approval","meaning":"No paid result was found by the current draft lookup.","next":"Check payment_lookup first. When lookup is available, give the customer the existing approval_url; do not infer refusal or failed payment."},{"status":"paid","meaning":"A successful Stripe payment was found for the draft.","next":"Use order_url where returned. Continue artwork/proof and fulfillment follow-up; paid does not mean produced or delivered."},{"status":"expired","meaning":"The draft lifetime ended and no paid result was returned.","next":"If payment may already have occurred, reconcile the receipt before issuing another payment request. The expired response does not reliably distinguish an unavailable payment lookup."},{"status":"payment_lookup: unavailable","meaning":"The API could not verify payment at this time.","next":"Treat payment as unknown, back off and reconcile it. Do not ask the customer to pay a second time merely because lookup failed."},{"status":"pickup · local_delivery · us_delivery · calculated","meaning":"Shipping has a defined mode or computed amount for the quoted configuration.","next":"Show the returned shippingMessage and total. These are pricing states, not delivery-progress states."},{"status":"needs_zip","meaning":"Delivery cannot be priced without the destination ZIP.","next":"Supply the ZIP or let the customer enter it on the approval page; null shipping is not free shipping."},{"status":"quote_required · not_shippable","meaning":"The requested delivery needs a separate quote or is unavailable in that configuration.","next":"Use the returned explanation, discuss a supported alternative such as pickup, or request a delivery quote."}],"errors":[{"code":"rate_limited","meaning":"The public request or tool-call limit was reached.","action":"Wait about a minute, then retry with backoff. REST returns HTTP 429; MCP can return isError: true inside a successful HTTP response."},{"code":"price_changed","meaning":"The draft's stored item prices no longer match current catalogue pricing.","action":"Get a fresh quote and show the new result to the customer before preparing a replacement draft."},{"code":"unknown_option · unknown_option_group · bad_quantity · turnaround_unavailable","meaning":"The requested configuration cannot be resolved from this product's current options.","action":"Read get_product again and use its actual choices and turnaround name. Show quantity adjustments to the customer."},{"code":"unknown_draft · bad_item_id · stale_item","meaning":"The supplied draft or configuration reference cannot be used as requested.","action":"Preserve the complete returned reference. Check which code was returned; an expired draft is a separate status. Do not guess or repair a signed token."},{"code":"not_configured · not_priceable · no_quantities","meaning":"A required service or catalogue configuration cannot currently serve this request.","action":"Do not invent a quote or treat this as customer approval. Retry later or use the documented customer support channels."},{"code":"bad_artwork_url","meaning":"An artwork reference failed the supported URL checks.","action":"Use an HTTPS URL within 480 characters. A valid reference is not proof that the file was downloaded or passed preflight."},{"code":"bad_json · body_too_large","meaning":"The request body is invalid JSON or exceeds the supported transport size.","action":"Correct the request or reduce it. Send artwork references, never file bytes or base64 data in a draft."},{"code":"server_error","meaning":"The operation did not return a trustworthy result.","action":"Retain the last confirmed result, retry with backoff and check state before repeating an action. A tool error is not a completed order."}],"limits":{"maxLines":7,"maxPackagesPerLine":1000,"maxArtworkFiles":10,"maxArtworkUrlChars":480,"maxNoteChars":1200},"requestsPerMinutePerIp":{"searchProducts":120,"getProduct":120,"getQuote":60,"createOrder":6,"checkOrder":60},"examples":{"config":"{\n  \"mcpServers\": {\n    \"angels-print\": {\n      \"type\": \"http\",\n      \"url\": \"https://angelsprint.com/api/mcp\"\n    }\n  }\n}","cli":"claude mcp add --transport http angels-print https://angelsprint.com/api/mcp\nclaude mcp get angels-print","initialize":"curl -sS https://angelsprint.com/api/mcp \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-06-18\",\"capabilities\":{},\"clientInfo\":{\"name\":\"my-print-agent\",\"version\":\"1.0\"}}}'","initialized":"curl -sS https://angelsprint.com/api/mcp \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'MCP-Protocol-Version: 2025-06-18' \\\n  --data '{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}'","listTools":"curl -sS https://angelsprint.com/api/mcp \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'MCP-Protocol-Version: 2025-06-18' \\\n  --data '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}'","toolCall":"curl -sS https://angelsprint.com/api/mcp \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'MCP-Protocol-Version: 2025-06-18' \\\n  --data '{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"get_quote\",\"arguments\":{\"slug\":\"classic-business-cards-160\",\"quantity\":500,\"fulfillment\":\"pickup\"}}}'","restSearch":"curl -sS 'https://angelsprint.com/api/agent/products?q=business+cards&limit=3'","restProduct":"curl -sS 'https://angelsprint.com/api/agent/products/classic-business-cards-160'","restQuote":"curl -sS https://angelsprint.com/api/agent/quote \\\n  -H 'Content-Type: application/json' \\\n  --data '{\"slug\":\"classic-business-cards-160\",\"quantity\":500,\"fulfillment\":\"pickup\"}' \\\n  > quote.json","restDraft":"# Requires curl + jq. Review quote.json first.\n# Replace the example email with the customer's authorized address.\njq -n --arg itemId \"$(jq -er '.itemId' quote.json)\" \\\n  '{items:[{itemId:$itemId,qty:1}],\n    fulfillment:\"pickup\",\n    operator:{email:\"customer@example.com\",name:\"Customer name\"},\n    agent:\"My print assistant\",\n    note:\"Confirm the required date with the customer\"}' > draft-request.json\n\ncurl -sS https://angelsprint.com/api/agent/orders \\\n  -H 'Content-Type: application/json' \\\n  --data-binary @draft-request.json > draft.json\n\n# Share this privately with the customer; the API does not email it.\njq -r '.approval_url' draft.json","restStatus":"# draft.json is private. Do not commit it or put it in public logs.\ndraft_id=\"$(jq -er '.draft_id' draft.json)\"\ncurl -sS \"https://angelsprint.com/api/agent/orders/$draft_id\"","artwork":"{\n  \"artwork\": [\n    {\n      \"name\": \"front-v3.pdf\",\n      \"url\": \"https://files.example.com/front-v3.pdf\"\n    },\n    {\n      \"name\": \"back-v3.pdf\",\n      \"url\": \"https://files.example.com/back-v3.pdf\"\n    }\n  ]\n}","prompt":"Help me order printing from Angels Print. Read https://angelsprint.com/api/agent/guide.\nConnect to https://angelsprint.com/api/mcp, or use https://angelsprint.com/api/agent/openapi.json.\nAsk for the product, dimensions, quantity, artwork, required date and pickup or delivery ZIP.\nRead the product's actual options, get a quote and show chosen, adjustments, shippingStatus and total.\nWith my permission, create one draft using the returned itemId and my email, then give me approval_url privately. I will review and pay.\nKeep payment, artwork validation, proof approval, production and delivery as separate facts. Never call a missing tool or invent a status.\nFor the stages outside this API, use the supported account and order-specific links described in the guide."},"questions":[{"q":"Can my AI use your tools without installing your application code?","a":"Yes. A compatible client calls the hosted MCP server or REST endpoints; it does not need the shop's private source code. Read tools/list or OpenAPI for the actual schemas. The JSON service guide makes the complete workflow available to your application."},{"q":"How do I connect a remote MCP client?","a":"Choose a remote HTTP/Streamable HTTP connection to https://angelsprint.com/api/mcp. No API key is required for the public tools. The configuration example is for clients supporting an HTTP mcpServers entry; other applications use their own connector UI. For Claude Code, use the shown command or a project .mcp.json. Do not assume every desktop client's configuration format is identical."},{"q":"What should a custom MCP implementation expect?","a":"Send initialize, accept the returned protocol version, then send notifications/initialized and tools/list. Send individual JSON-RPC messages over POST with Accept: application/json, text/event-stream and the negotiated MCP-Protocol-Version. This server replies with JSON and currently issues no session ID. GET is a discovery description, not an SSE event stream; resources/list and prompts/list return empty lists. A tool result can contain structuredContent or JSON text in content; check isError before using it."},{"q":"Can an AI talk directly to your sales or production agents?","a":"Public tools remain unauthenticated catalogue/draft operations. The separate private-work MCP supports authenticated, order-scoped factual questions and persisted answers; it does not execute custom changes or contact staff. The website's Clip assistant helps select and price products and can collect a new quote request. Existing-order conversations can use Messages in the signed-in account, or reply to the order email at hello@angelsprint.com. The private-work conversation is separate from email and general account messages; Clip is not the authenticated order-status agent."},{"q":"Can an agent read all my uploaded files or approve a proof?","a":"The private-work MCP can list metadata for customer-supplied files on explicitly account-linked work. It cannot download file bytes, issue upload capabilities or submit a proof decision. Use only order-specific links or the customer's own account with their permission. Ask for a missing link rather than guessing a token. The customer approves the actual proof version through the supplied page."},{"q":"Does an accepted upload or AI-generated image mean print-ready?","a":"No. Upload controls enforce transport requirements such as type and size. They do not verify finished dimensions, resolution, bleed, fonts, color or cut paths. File preflight and proof approval are separate steps; full automated preflight is not exposed by the current public agent API."},{"q":"What should I include when asking about an existing order?","a":"Send the actual order reference if available, the email used to order, a short question, the relevant file version and any supporting photos. Reply in the existing order thread or use authenticated account messages. Keep signed drafts, artwork/proof tokens and customer files private. Never send card numbers or security codes."},{"q":"Can the API complete production and delivery by itself?","a":"The current public interface stops at draft preparation and payment lookup. The journey continues through file review, customer proof approval, recorded production updates and pickup or delivery information. The private-work API adds authenticated recorded facts and scoped factual conversation. Autonomous file validation, production control and confirmed delivery still require additional integrations and verified execution; those capabilities are not implied by this guide."}]}