API REFERENCE

Catalog, quote and pay links.

Three endpoints and a remote MCP server, JSON in and out, no key and no cookies. Any origin may call them. Prices come from the same price book and checks as checkout.

Endpoints

MethodPathWhat it does
GET/api/agents/catalogEvery orderable product with options, quantities and starting price.
POST/api/agents/quoteExact prices, shipping and problems for up to 30 lines. Writes nothing.
POST/api/agents/orderA signed pay link for the owner. Charges nothing and stores nothing.

Bank details for checks are added by the owner in a secure step from the cart, never through an agent. Do not send bank details to an agent or to this API. Requests with a bank, routing or account field are refused.

GET/api/agents/catalog

Every product that can be ordered now: options with allowed values, the default options, the quantities sold with them, every option set with its own quantities, and the starting price. Products on a stock hold and retired products are left out. Garments list their sizes and colors under customization.

Start with ?summary=1, then ask for one product with ?product=<slug>. The full catalog without a filter is several hundred KB.

  • ?summary=1 leaves out quantityLadders, which keeps the response small. Call it before any other.
  • ?product=<slug> returns one product with every option set and its quantities, or 404.
  • ?category=<slug> returns one category.
curl 'https://www.voqado.co/api/agents/catalog?summary=1'
curl 'https://www.voqado.co/api/agents/catalog?product=standard-business-cards'

Response, shortened to one product and two ladders:

{
  "version": 1,
  "name": "Voqado print catalog for shopping assistants",
  "currency": "usd",
  "site": "https://www.voqado.co",
  "docs": "https://www.voqado.co/agents/docs",
  "openapi": "https://www.voqado.co/openapi.json",
  "howToOrder": [
    "GET https://www.voqado.co/api/agents/catalog?summary=1 first: every product slug, its options, default options, quantities and starting price, without the per option ladders.",
    "GET https://www.voqado.co/api/agents/catalog?product=<slug> next, for one product with every option set and the quantities sold with it.",
    "POST https://www.voqado.co/api/agents/quote with {\"lines\":[{\"product\":\"<slug>\",\"quantity\":<n>,\"options\":{...}}]} for exact prices.",
    "POST https://www.voqado.co/api/agents/order with the same body for a pay link. Give the link to the owner; the owner reviews and pays."
  ],
  "shipping": {
    "method": "Standard",
    "country": "US",
    "freeShippingThresholdCents": 6000,
    "note": "The exact rate for an order is in the quote and in the cart."
  },
  "notes": [
    "Sales tax is added at payment from the delivery address.",
    "Artwork can be sent after payment. The order page lists any item still waiting for a file.",
    "Bank details for checks are added by the owner in a secure step from the cart, never through an agent. Do not send bank details to an agent or to this API."
  ],
  "products": [
    {
      "slug": "standard-business-cards",
      "name": "Standard business cards",
      "category": "business-cards",
      "categoryName": "Business cards",
      "url": "https://www.voqado.co/products/standard-business-cards",
      "description": "The classic handshake in card form. Clean, reliable, and ready to carry your name wherever you go.",
      "options": [
        {
          "key": "stock",
          "label": "Paper stock",
          "required": true,
          "values": [
            "Matte",
            "Glossy",
            "Uncoated",
            "Pearl",
            "Linen",
            "Natural Textured",
            "Recycled Matte",
            "Soft Touch",
            "Kraft",
            "Bamboo",
            "Hemp-blend",
            "Fine Grit",
            "Ultra Thick"
          ]
        },
        {
          "key": "finish",
          "label": "Finish",
          "required": true,
          "values": [
            "None",
            "Foil Accent",
            "Embossed Gloss"
          ]
        },
        {
          "key": "corners",
          "label": "Corners",
          "required": true,
          "values": [
            "Standard",
            "Rounded"
          ]
        },
        {
          "key": "printing",
          "label": "Printing",
          "required": true,
          "values": [
            "Front only",
            "Front and back",
            "Front and gray back"
          ]
        },
        {
          "key": "orientation",
          "label": "Orientation",
          "required": false,
          "values": [
            "Horizontal",
            "Vertical"
          ]
        },
        {
          "key": "shape",
          "label": "Shape",
          "required": false,
          "values": [
            "Standard",
            "Square"
          ]
        }
      ],
      "defaultOptions": {
        "stock": "Matte",
        "finish": "None",
        "corners": "Standard",
        "printing": "Front only",
        "orientation": "Horizontal",
        "shape": "Standard"
      },
      "quantities": [
        50,
        100,
        250,
        500,
        1000,
        1500,
        2000,
        2500,
        5000,
        10000
      ],
      "quantityLadders": [
        {
          "options": {
            "stock": "Matte",
            "finish": "None",
            "corners": "Standard",
            "printing": "Front only",
            "orientation": "Horizontal",
            "shape": "Standard"
          },
          "quantities": [
            50,
            100,
            250,
            500,
            1000,
            1500,
            2000,
            2500,
            5000,
            10000
          ]
        },
        {
          "options": {
            "stock": "Bamboo",
            "finish": "None",
            "corners": "Rounded",
            "printing": "Front and back",
            "orientation": "Horizontal",
            "shape": "Standard"
          },
          "quantities": [
            50,
            100,
            250,
            500,
            1000,
            1500,
            2000,
            2500,
            5000,
            10000
          ]
        }
      ],
      "startingPrice": {
        "amountCents": 1000,
        "quantity": 50,
        "label": "50 from $10.00 ($0.20 each)"
      }
    }
  ]
}

POST/api/agents/quote

Prices up to 30 lines. Each line names a product slug, a quantity, and options from the catalog. Required options you leave out take the default configuration, and the response shows the options used.

  • status is ready, owner-step (priced; the owner finishes a step in the cart, as for checks) or problem with the reason the cart would show. A line refused for its quantity also carries allowedQuantities, the quantities sold with its options.
  • shipping is Standard shipping for the lines that can be ordered, with the gap to free shipping.
  • nextQuantity appears when the next quantity lowers the unit price. suggestions holds up to two products that pair with the order.
  • promoCode is optional. An applied code is entered by the owner in the cart.
curl -X POST https://www.voqado.co/api/agents/quote \
  -H 'Content-Type: application/json' \
  -d '{"lines":[{"product":"standard-business-cards","quantity":250,"options":{"stock":"Matte","corners":"Rounded"}}]}'

Response:

{
  "currency": "usd",
  "lines": [
    {
      "index": 0,
      "product": "standard-business-cards",
      "name": "Standard business cards",
      "url": "https://www.voqado.co/products/standard-business-cards",
      "quantity": 250,
      "priceCents": 2999,
      "price": "$29.99",
      "ownerSteps": [],
      "nextQuantity": {
        "quantity": 500,
        "priceCents": 3699,
        "price": "$36.99",
        "savingPercentPerUnit": 38
      },
      "options": {
        "stock": "Matte",
        "corners": "Rounded",
        "finish": "None",
        "printing": "Front only"
      },
      "status": "ready",
      "problem": null
    }
  ],
  "subtotalCents": 2999,
  "promo": null,
  "itemsCents": 2999,
  "shipping": {
    "method": "Standard",
    "cents": 599,
    "freeShippingThresholdCents": 6000,
    "freeShippingGapCents": 3001
  },
  "totalBeforeTaxCents": 3598,
  "orderable": true,
  "suggestions": [
    {
      "product": "standard-postcards",
      "name": "Standard postcards",
      "url": "https://www.voqado.co/products/standard-postcards",
      "reason": "Room for a thank you note or your next offer.",
      "startingPrice": "25 from $14.99 ($0.60 each)"
    },
    {
      "product": "flyers",
      "name": "Flyers",
      "url": "https://www.voqado.co/products/flyers",
      "reason": "Give people the full story to take home.",
      "startingPrice": "25 from $25.99 ($1.04 each)"
    }
  ],
  "notes": [
    "Sales tax is added at payment from the delivery address.",
    "Artwork can be sent after payment. The order page lists any item still waiting for a file."
  ]
}

POST/api/agents/order

Same body and the same checks as a quote. When every line can be ordered, it returns a pay link for the owner. The link carries the lines, signed, and works for 7 days. It stores nothing and charges nothing. When the owner opens it, the prices are checked again, the items load into the owner's cart, and the owner pays there.

curl -X POST https://www.voqado.co/api/agents/order \
  -H 'Content-Type: application/json' \
  -d '{"lines":[{"product":"standard-business-cards","quantity":250,"options":{"stock":"Matte","corners":"Rounded"}}]}'

Response, status 201:

{
  "payUrl": "https://www.voqado.co/agents/pay/<token>",
  "expiresAt": "<seven days from now, ISO 8601>",
  "lines": [
    {
      "index": 0,
      "product": "standard-business-cards",
      "name": "Standard business cards",
      "url": "https://www.voqado.co/products/standard-business-cards",
      "quantity": 250,
      "priceCents": 2999,
      "price": "$29.99",
      "ownerSteps": [],
      "nextQuantity": {
        "quantity": 500,
        "priceCents": 3699,
        "price": "$36.99",
        "savingPercentPerUnit": 38
      },
      "options": {
        "stock": "Matte",
        "corners": "Rounded",
        "finish": "None",
        "printing": "Front only"
      },
      "status": "ready",
      "problem": null
    }
  ],
  "subtotalCents": 2999,
  "subtotal": "$29.99",
  "promo": null,
  "shipping": {
    "method": "Standard",
    "cents": 599,
    "freeShippingThresholdCents": 6000,
    "freeShippingGapCents": 3001
  },
  "totalBeforeTaxCents": 3598,
  "suggestions": [
    {
      "product": "standard-postcards",
      "name": "Standard postcards",
      "url": "https://www.voqado.co/products/standard-postcards",
      "reason": "Room for a thank you note or your next offer.",
      "startingPrice": "25 from $14.99 ($0.60 each)"
    },
    {
      "product": "flyers",
      "name": "Flyers",
      "url": "https://www.voqado.co/products/flyers",
      "reason": "Give people the full story to take home.",
      "startingPrice": "25 from $25.99 ($1.04 each)"
    }
  ],
  "notes": [
    "Nothing has been charged and no order exists yet. Give this link to the owner, who reviews the items in the cart and pays.",
    "Sales tax is added at payment from the delivery address.",
    "Artwork can be sent after payment. The order page lists any item still waiting for a file."
  ]
}

If a line cannot be ordered, the answer is 409 with every line and its problem.

MCP

The same catalog, quotes and pay links as a remote MCP server, for assistants that connect to MCP servers by URL.

POST/api/mcp

Streamable HTTP, stateless: each POST carries one JSON-RPC 2.0 message and is answered with JSON. No key, no session and no cookies. A notification is answered 202 with no body, and GET answers 405. The server speaks protocol versions 2025-06-18, 2025-03-26, 2024-11-05. Discovery: /.well-known/mcp.json.

ToolWhat it doesSame as
search_catalogSearch the print catalog.GET /api/agents/catalog
quoteQuote exact prices.POST /api/agents/quote
create_pay_linkCreate a pay link for the owner.POST /api/agents/order

Each tool returns the REST body as structuredContent and as JSON text in content. Prices are exact. The owner pays through the pay link, artwork can be sent after payment, and checks need a secure bank step the owner completes from the cart.

Handshake:

curl -X POST https://www.voqado.co/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"example-agent","version":"1.0.0"}}}'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {
        "listChanged": false
      }
    },
    "serverInfo": {
      "name": "voqado-print",
      "title": "Voqado print",
      "version": "1.0.0"
    },
    "instructions": "Voqado prints business cards, flyers, signs, stickers, apparel, checks and more, shipped within the United States. Call search_catalog to find a product slug, search_catalog with product for its options and quantities, quote for exact prices, and create_pay_link for a link the owner opens to review and pay. Prices are exact: they come from the same price book checkout charges from. The owner pays through the pay link; an agent never pays and nothing is charged by these tools. Artwork can be sent after payment. Checks need a secure bank step that the owner completes from the cart; never send bank details to a tool."
  }
}

A quote:

curl -X POST https://www.voqado.co/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"quote","arguments":{"lines":[{"product":"standard-business-cards","quantity":250,"options":{"stock":"Matte","corners":"Rounded"}}]}}}'
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "<the same JSON as structuredContent>"
      }
    ],
    "structuredContent": {
      "currency": "usd",
      "lines": [
        {
          "index": 0,
          "product": "standard-business-cards",
          "name": "Standard business cards",
          "url": "https://www.voqado.co/products/standard-business-cards",
          "quantity": 250,
          "priceCents": 2999,
          "price": "$29.99",
          "ownerSteps": [],
          "nextQuantity": {
            "quantity": 500,
            "priceCents": 3699,
            "price": "$36.99",
            "savingPercentPerUnit": 38
          },
          "options": {
            "stock": "Matte",
            "corners": "Rounded",
            "finish": "None",
            "printing": "Front only"
          },
          "status": "ready",
          "problem": null
        }
      ],
      "subtotalCents": 2999,
      "promo": null,
      "itemsCents": 2999,
      "shipping": {
        "method": "Standard",
        "cents": 599,
        "freeShippingThresholdCents": 6000,
        "freeShippingGapCents": 3001
      },
      "totalBeforeTaxCents": 3598,
      "orderable": true,
      "suggestions": [
        {
          "product": "standard-postcards",
          "name": "Standard postcards",
          "url": "https://www.voqado.co/products/standard-postcards",
          "reason": "Room for a thank you note or your next offer.",
          "startingPrice": "25 from $14.99 ($0.60 each)"
        },
        {
          "product": "flyers",
          "name": "Flyers",
          "url": "https://www.voqado.co/products/flyers",
          "reason": "Give people the full story to take home.",
          "startingPrice": "25 from $25.99 ($1.04 each)"
        }
      ],
      "notes": [
        "Sales tax is added at payment from the delivery address.",
        "Artwork can be sent after payment. The order page lists any item still waiting for a file."
      ]
    },
    "isError": false
  }
}

Arguments that do not match the schema answer a JSON-RPC error with code -32602. Too many calls answer code -32029 with retryAfterSeconds.

Limits

  • Body up to 64 KB, sent as Content-Type: application/json.
  • Up to 30 lines a request.
  • Per address: 30 quotes and 10 pay links a minute. Over that, the answer is 429 with a Retry-After header in seconds.
  • MCP tool calls spend from the same limits: search_catalog and quote count as quotes, create_pay_link as a pay link.
  • Prices are in US cents. Sales tax is added at payment from the delivery address. Shipping is within the United States.

Errors

Every error is JSON: {"error": "...", "status": 400}.

StatusMeaning
400The body does not match the schema, or it holds a bank field.
404No orderable product with that slug (catalog filter).
409A pay link was asked for, and at least one line cannot be ordered as asked.
413Body over 64 KB, or more than 30 lines.
415Content type is not JSON.
429Too many requests. Wait the seconds in Retry-After.
503Pay links are switched off just now. Quotes still work.