# Print quote skill — Complete Print & Design

Use when a user wants print, signage, display, or design quotes from our Nerang production base.

Guide for people and agents: https://www.completeprint.design/for-agents

## Coverage
- Production base: Nerang, QLD 4211
- Corridors: Gold Coast and Tweed; South East Queensland; Wide Bay and Burnett
- National accounts: https://www.completeprint.design/services/national-accounts
- Service areas index: https://www.completeprint.design/service-areas

## Fulfilment (public posture)
- Pickup: Pick up from our studio on Brendan Drive, Nerang, during opening hours.
- Delivery: Delivery is quoted for each job, based on its size, weight, where it's going and when you need it.
- Installation: Need it installed? Ask us about availability for your project and location.

## Preview before sending
POST /api/agent/quote/preview (or preview_quote on the current tool surface) checks a brief without saving, submitting, emailing, uploading or creating a quote reference/token. Contact may be omitted or partial. HTTP 200 can still report an incomplete brief: read briefValid, submissionFieldsValid, missingSubmissionFields and errors. readyForUserApproval is not permission or acceptance. Staff still confirm price, availability and timing.
Catalogue searchTerms are retrieval-only vocabulary. quoteGuidance.singlePublishedOptions is a source constraint, not a customer preference or automatic default; confirm it. Never infer defaults from option order or count. Preserve known facts and use explicit customer discussion intent for unresolved specifications.

## Steps
1. GET /api/catalog to list product slugs, coverage and specs.
2. Carry the known brief forward. Match each product to productSlug (or `custom-enquiry`), retain its quantity, productSpecs and notes, and ask only for missing required details. Off-guide details belong in custom_notes for staff review, not invented catalogue options.
   If the customer explicitly requests discussion of an item's remaining specifications, set discussSpecifications true on that line and retain every known fact. The server represents unresolved required text dimensions (including fridge-magnet size) and selectors as discussion requests; never invent internal UI markers. False or omitted retains normal validation. A single-item request without lineItems can instead use the top-level flag with productSlug; never use the top-level flag for a multi-item brief. Custom enquiries still require meaningful productSpecs.scope.
   Keep the customer's explanation in custom_notes. Field-specific advice_requested remains limited to source select/multi-select keys, not free-text size. Printer standard is not a stock selection when several catalogue options exist without an authoritative default: ask which option, or obtain explicit permission for staff discussion instead of guessing.
3. Show the complete brief and obtain the user's permission to send it and their contact details to CPD. POST /api/agent/quote with contact and either productSlug/productSpecs or lineItems containing the complete 1–20-item brief. Include a stable submissionId (8–120 characters), reused with the unchanged payload on retry. No API key is required.
4. Optional: send X-Agent-Api-Key only if you have a partner key. Omit the header for public access. A wrong key returns 401 — omit the header and retry.
5. Keep marketingAuthorised false or omitted unless the user separately opts in to print tips/offers. Omit the legacy website honeypot field or leave it empty; a customer's website belongs in notes.
6. Pass X-Agent-Id header when quoting on behalf of a client.
7. Poll GET /api/agent/quote/{referenceId} for status updates. Public for CPD- references; no key required.
8. Return referenceId and statusUrl, distinguish quote acceptance from artwork receipt, and tell the user CPD staff will review the request personally; do not promise a response-time guarantee.

## Example: four items, known facts plus authorised discussion
This illustrative customer explicitly chose the flyer specifications, requested staff discussion on the other three items, and approved sending the complete brief. Replace the example facts/contact with the customer's actual approved information; do not default discussion flags to true. Neither artwork nor marketing authority is implied. External signage remains a custom request, not a confirmed core product or installation commitment.
```json
{
  "submissionId": "example-approved-brief-001",
  "contact": {
    "name": "Example Customer",
    "email": "customer@example.test",
    "phone": "0400000000",
    "customerType": "personal"
  },
  "artworkStatus": "not-sure",
  "lineItems": [
    {
      "productSlug": "business-cards",
      "quantity": "500",
      "discussSpecifications": true,
      "productSpecs": {
        "size": "90mm x 55mm",
        "custom_notes": "Customer asked for printer-standard stock without choosing Gloss or Satin, and explicitly requested discussion of the remaining specifications."
      }
    },
    {
      "productSlug": "flyers",
      "quantity": "1000",
      "productSpecs": {
        "size": "148mm x 210mm (A5)",
        "stock-material": "150gsm Gloss",
        "printing-sides": "Both sides"
      },
      "notes": "These flyer specifications were explicitly chosen by the customer; they are not assumed defaults."
    },
    {
      "productSlug": "fridge-magnets",
      "quantity": "250",
      "discussSpecifications": true,
      "productSpecs": {
        "custom_notes": "Customer wants promotional fridge magnets and explicitly requested help choosing dimensions and remaining specifications."
      }
    },
    {
      "productSlug": "custom-enquiry",
      "quantity": "1",
      "discussSpecifications": true,
      "productSpecs": {
        "scope": "External shop-front sign displaying the business name. Customer requests discussion of dimensions, material, installation feasibility and any approvals.",
        "custom_notes": "Custom request for staff review; availability and installation are not confirmed."
      }
    }
  ]
}
```

## Tool capability
Check available tools before promising execution. A disconnected browser, fetch-only tool or tool/proxy refusal is not proof of a website rejection. State the actual limitation, respect access restrictions, and never claim submission without the accepted response. The current browser cannot resume an arbitrary API-created accepted quote by reference; retain that reference rather than creating a duplicate.

## Artwork authority and private upload
- Before sending files, obtain explicit confirmation that the user has authority to supply them to CPD for quoting/production under its privacy policy. Set artworkAttested true only for that confirmation; access to an attachment or AI-generated artwork is not consent. Use artworkStatus have-files when supplying files now.
- Submit the quote before uploading bytes. After acceptance, POST /api/quote/intake-token with submission_id equal to referenceId and the quote contact email; include recovery_capability only if supplied by the accepted response.
- Follow artworkUpload.next: pending permits starting the upload, retry_required preserves the accepted quote while access needs retry, not_requested means no upload was requested, and not_renewed means historical replay grants no renewed capability. Search access alone cannot upload; the assistant needs authorised file bytes and a compatible upload client.
- Use the returned short-lived intake_token to POST /api/hunter/artwork/grant with submission_id, filename, content_type and size_bytes. The grant checks durable artwork authority, reference binding, file constraints and rate limits.
- For transport server-proxy, POST multipart file, submission_id and grant_id to /api/hunter/artwork/upload. For blob-direct, use the returned restricted upload capability, then POST JSON finalization there using submission_id, grant_id, granted pathname, filename, content_type, size_bytes and the actual SHA-256. Do not fetch arbitrary artwork URLs or invent storage references.
- The existing blob-direct client imports put from @vercel/blob/client and calls await put(grant.blob_pathname, file, { access: 'private', token: grant.blob_client_token, contentType: file.type || 'application/octet-stream', multipart: file.size > Math.floor(4.5 * 1024 * 1024) }). Use the exact granted pathname and restricted token, then finalize with the file's SHA-256; optional blob_url must come only from that upload's result. The grant does not return a generic upload URL.
- Keep tokens and recovery capabilities private: no public links, logs, examples or ordinary chat output. Expired or historical-replay access must not be silently renewed.
- A failed upload never cancels an accepted quote. Preserve its reference and follow retry guidance; do not create another quote. Do not blindly re-upload after an indeterminate or recovery-required storage result. Report artwork receipt only after finalization confirms custody.
- Check capability before capture: if this assistant cannot transfer authorised bytes with the supported transport, choose the browser quote/upload flow before submitting. After API acceptance, use a capable authorised client or contact CPD with the existing reference. The browser quote page cannot resume an arbitrary API-created quote by reference; never submit a duplicate or claim upload success.

## Private save, share and resume
- Save only when the customer explicitly asks or permits it: POST /api/quote/drafts accepts {brief:{lineItems,notes?,projectDeadline?,artworkStatus?,deliveryMode?,installationRequested?}}. It is separate from preview and does not submit a quote, email staff, upload artwork or create an order.
- Drafts exclude contact, addresses, artwork bytes/references, detailed fulfilment and consent fields; optional artworkStatus/deliveryMode/installationRequested are planning choices, not authority or promises. Free text can still contain personal data: warn the customer not to include contact details, files, confidential content or secrets. Anyone with the read link can view; anyone with the edit link can change or revoke. Share only with the customer's intended recipient and permission.
- Generate a SECRET Idempotency-Key as v1.<current Unix seconds>.<32 cryptographically random bytes encoded base64url>. This is a root capability secret that can recover both read and edit access. Preserve it privately for an exact creation retry; never copy a fixed example. The original seven-day expiry is not extended by reading, editing or retrying. Changed creation content conflicts; expired keys do not revive links.
- Read GET /api/quote/drafts/{draftId} with the returned private read/edit bearer capability. PATCH requires editor capability, current revision, stable mutationId and the new brief; stale versions conflict rather than silently overwriting. DELETE with editor capability and current revision revokes the whole draft/all links, not a separately accepted quote.
- Use only returned fragment-based private review/edit links; capabilities must never go in URL queries, logs, public indexes, analytics or browser persistence. These are private data disclosures, not ordinary public website links. Browser calls are same-origin; a suitable authorised server-side client can use the documented API. Store unavailable means not saved, never pretend success.
- To submit, review the current brief and map planning choices to the existing submit contract, not a blind copy of the saved-draft body: apply an explicit project deadline to appropriate line deadlines, collect the actual destination for delivery-quote, retain installation as a request for staff review, and obtain separate artwork authority. Collect required contact/fulfilment/artwork choices separately, obtain explicit permission and use a stable submissionId. A saved draft or preview is not consent, quote acceptance, pricing confirmation or artwork custody.

## MCP tools
Connect /api/mcp for search_products, get_product, preview_quote, submit_quote, get_quote_status.
This is CPD's current HTTP JSON-RPC tool surface, not standards-grade MCP transport or a guarantee that every assistant can connect. The documented REST and browser flows remain available.

## Endpoints
- Catalog: https://www.completeprint.design/api/catalog
- Preview (no send): POST https://www.completeprint.design/api/agent/quote/preview
- Guide: https://www.completeprint.design/for-agents
- Quote: POST https://www.completeprint.design/api/agent/quote
- Status: GET https://www.completeprint.design/api/agent/quote/{referenceId}
- MCP: https://www.completeprint.design/api/mcp
- OpenAPI: https://www.completeprint.design/openapi.json
- Human form: https://www.completeprint.design/quote

## Business
- Phone: 07 5596 3767
- Hours: Monday to Friday, 7am to 2pm
- Email: hello@completeprint.design
