Skip to main content
Glama

kapruka_create_order

Idempotent

Create a guest-checkout order on Kapruka and return a click-to-pay link.

Builds a Kapruka order from the supplied cart + recipient + delivery + sender,
then returns a checkout URL the customer opens in a browser to complete payment.
No Kapruka account is required. Prices are locked for the lifetime of the link
(60 minutes) — the customer pays exactly the quoted grand total even if the
catalog price changes meanwhile.

Free public tier limits: 30 orders per hour per client IP. Cart up to 30 items,
quantity up to 99 per item. A fresh idempotency key is generated per call so
retries on transient errors return the same checkout URL rather than duplicates.

Args:
    params (CreateOrderInput):
        - cart (list[CartItem]): 1–30 lines. Catalogue line: product_id, quantity (default 1), optional icing_text (cakes only).
          Custom cake line: custom_cake_request_id + phone — orders the cake Kapruka staff quoted via
          kapruka_custom_cake_status (status must be 'quoted'; quantity is always 1; never send a price).
          Lines can be mixed in one order — one delivery fee covers everything; the whole cart must be
          deliverable to delivery.city. Only place a custom cake order after the customer clearly
          accepted the quoted total.
        - recipient (Recipient): name + phone (E.164 +9477… or local 077…)
        - delivery (Delivery): address, city (must be Kapruka-deliverable — use kapruka_list_delivery_cities), location_type (house/apartment/office/other, default house), date (YYYY-MM-DD, today-or-future Asia/Colombo), optional instructions, type ('standard' default | 'economy')
        - sender (Sender): name + anonymous flag
        - gift_message (Optional[str]): Up to 300 chars
        - currency (str): LKR (default), USD, GBP, AUD, EUR
        - response_format (str): 'markdown' (default) or 'json'

Returns:
    str: Order confirmation with checkout URL.

    JSON schema:
    {
      "checkout_url": str,           # Open in browser to pay (no login required)
      "order_ref": str,              # e.g. "ORD-20260520-7823"
      "order_id": str,               # id used by the bank-deposit flow
      "summary": {
        "items_total":   number,
        "delivery_fee":  number,
        "addons_total":  number,
        "grand_total":   number,     # items_total + delivery_fee + addons_total
        "currency":      str,
        "delivery_type": "standard" | "economy",
        "delivery_date": str,        # the date checkout will use — may differ from the one sent
        "delivery_promise": str      # economy only: quote as given
      },
      "expires_at": str              # ISO 8601 — link stops working after this
    }

    Error: "Error (<code>): <message>" on failure. Common codes:
      empty_cart, missing_field, past_delivery_date, product_not_found,
      product_out_of_stock, city_not_deliverable (city not in the network at
      all), date_not_deliverable, city_not_deliverable_for_item.

    Custom cake lines add: request_not_found (404 — wrong id/phone or staff
    removed it), quote_not_ready (409 — staff haven't priced it; check
    kapruka_custom_cake_status later), quote_expired (410 — submit a new
    kapruka_custom_cake_request). summary.items_total may differ from the
    quoted cake total by a few rupees (USD round-trip) — quote the summary
    numbers when asking for payment.

    economy_not_available (HTTP 422): economy was requested but this order
    cannot go economy. Nothing is created. Tell the customer it goes by
    standard delivery (fee from kapruka_check_delivery) and, once they agree,
    resend with delivery.type 'standard' and their date.

    Economy-only items always go economy, even when 'standard' is sent; read
    summary.delivery_type and summary.delivery_date and tell the customer the
    date checkout will use.

    city_not_deliverable_for_item (HTTP 422): at least one cart item (food /
    hotel cake / liquor) cannot reach delivery.city. NOTHING is created — the
    API never places a partial order and neither should you. The error text
    names every blocking item and lists the cities the whole cart CAN go to.
    Tell the customer which item blocks the order and offer to (a) change the
    city to one of those, or (b) remove/replace that item. Never retry with
    the same city. Avoid this entirely by calling kapruka_check_delivery with
    `product_id` for each limited item before ordering.

Input Schema

NameRequiredDescriptionDefault
paramsYes

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changed
    • changedInput schema / $defs / Delivery / properties / city / description
      Previous value: -"Must be a Kapruka delivery city (canonical name from kapruka_list_delivery_cities) that EVERY cart item can reach. The order ships as one shipment, so food / hotel cake / liquor items restrict the whole cart to their city set — verify with kapruka_check_delivery(city, product_id) first; otherwise the order is rejected with city_not_deliverable_for_item."New value: +"Sri Lanka orders: a Kapruka delivery city (canonical name from kapruka_list_delivery_cities) that EVERY cart item can reach. International gifts: the recipient's city/town abroad, as written. The order ships as one shipment, so food / hotel cake / liquor items restrict the whole cart to their city set — verify with kapruka_check_delivery(city, product_id) first; otherwise the order is rejected with city_not_deliverable_for_item."
    • addedInput schema / $defs / Delivery / properties / country
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 60,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "International gifts only (required): the store country from kapruka_gift_countries.",
      +  "title": "Country"
      +}
    • changedInput schema / $defs / Delivery / properties / type / description
      Previous value: -"'standard' (default) or 'economy' — the cheaper courier option. Send 'economy' only when kapruka_check_delivery (with the cart) showed it and the customer chose it, or said the items go by economy only. Economy orders are dated 4 days ahead for you; `date` is then ignored."New value: +"'international_gift' for products from kapruka_gift_country_products (recipient abroad; needs country, zip, zone where listed; date >= 3 days ahead). Otherwise 'standard' (default) or 'economy' — the cheaper courier option. Send 'economy' only when kapruka_check_delivery (with the cart) showed it and the customer chose it, or said the items go by economy only. Economy orders are dated 4 days ahead for you; `date` is then ignored."
    • addedInput schema / $defs / Delivery / properties / zip
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 35,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "International gifts only (required): the recipient's postcode / ZIP.",
      +  "title": "Zip"
      +}
    • addedInput schema / $defs / Delivery / properties / zone
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 60,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "International gifts only: required for Australia and the UAE — one of that country's listed zones (kapruka_gift_countries).",
      +  "title": "Zone"
      +}
    • addedInput schema / $defs / Sender / properties / email
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 120,
      +      "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Sender's email (international gifts: send it when you have it).",
      +  "title": "Email"
      +}
  2. Changed1 schema field changed
    • addedInput schema / $defs / Delivery / properties / type
      Added value: +{
      +  "default": "standard",
      +  "description": "'standard' (default) or 'economy' — the cheaper courier option. Send 'economy' only when kapruka_check_delivery (with the cart) showed it and the customer chose it, or said the items go by economy only. Economy orders are dated 4 days ahead for you; `date` is then ignored.",
      +  "title": "Type",
      +  "type": "string"
      +}
  3. Changed1 schema field changed
    • changedInput schema / $defs / CreateOrderInput / properties / currency / description
      Previous value: -"Pricing currency. Supported: LKR, USD, GBP, AUD, CAD, EUR."New value: +"Pricing currency. Supported: LKR, USD, GBP, AUD, EUR."
  4. Changed17 schema fields changed
    • addedInput schema / $defs / CartItem / description
      Added value: +"One cart line — EITHER a catalogue product OR a quoted custom cake.\n\nCatalogue line:   {\"product_id\": \"...\", \"quantity\": 1, \"icing_text\": \"...\"}\nCustom cake line: {\"custom_cake_request_id\": \"...\", \"phone\": \"+9477...\"}\nThe custom cake line is turned into the staff-quoted cake server-side\n(name, picture, price); quantity is always 1 and no price is ever sent."
    • addedInput schema / $defs / CartItem / properties / custom_cake_request_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 80,
      +      "minLength": 6,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "request_id of a custom cake that kapruka_custom_cake_status reports as 'quoted'. Orders the staff-quoted cake (quantity 1). Requires `phone`.",
      +  "title": "Custom Cake Request Id"
      +}
    • changedInput schema / $defs / CartItem / properties / icing_text / description
      Previous value: -"Cake icing text. Silently ignored for non-cake products."New value: +"Cake icing text. Silently ignored for non-cake products. Catalogue lines only."
    • addedInput schema / $defs / CartItem / properties / phone
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 30,
      +      "minLength": 7,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The customer.phone the custom cake request was made with (custom cake lines only).",
      +  "title": "Phone"
      +}
    • addedInput schema / $defs / CartItem / properties / product_id / anyOf
      Added value: +[
      +  {
      +    "maxLength": 80,
      +    "minLength": 3,
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / $defs / CartItem / properties / product_id / default
      Added value: +null
    • changedInput schema / $defs / CartItem / properties / product_id / description
      Previous value: -"Kapruka product ID (e.g. 'cakeXX000000')."New value: +"Kapruka product ID (e.g. 'cakeXX000000'). Catalogue line."
    • removedInput schema / $defs / CartItem / properties / product_id / maxLength
      Removed value: -80
    • removedInput schema / $defs / CartItem / properties / product_id / minLength
      Removed value: -3
    • removedInput schema / $defs / CartItem / properties / product_id / type
      Removed value: -"string"
    • addedInput schema / $defs / CartItem / properties / quantity / anyOf
      Added value: +[
      +  {
      +    "maximum": 99,
      +    "minimum": 1,
      +    "type": "integer"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / $defs / CartItem / properties / quantity / default
      Previous value: -1New value: +null
    • changedInput schema / $defs / CartItem / properties / quantity / description
      Previous value: -"Quantity (1–99)."New value: +"Quantity (1–99, default 1). Catalogue lines only."
    • removedInput schema / $defs / CartItem / properties / quantity / maximum
      Removed value: -99
    • removedInput schema / $defs / CartItem / properties / quantity / minimum
      Removed value: -1
    • removedInput schema / $defs / CartItem / properties / quantity / type
      Removed value: -"integer"
    • removedInput schema / $defs / CartItem / required
      Removed value: -[
      -  "product_id"
      -]
  5. Changed1 schema field changed
    • changedInput schema / $defs / Delivery / properties / city / description
      Previous value: -"Must be a Kapruka delivery city — use kapruka_list_delivery_cities to look up valid names."New value: +"Must be a Kapruka delivery city (canonical name from kapruka_list_delivery_cities) that EVERY cart item can reach. The order ships as one shipment, so food / hotel cake / liquor items restrict the whole cart to their city set — verify with kapruka_check_delivery(city, product_id) first; otherwise the order is rejected with city_not_deliverable_for_item."
  6. Changed1 schema field changed
    • changedInput schema / $defs / CartItem / properties / product_id / description
      Previous value: -"Kapruka product ID (e.g. 'cake00ka002034')."New value: +"Kapruka product ID (e.g. 'cakeXX000000')."
  7. Added

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (idempotentHint, readOnlyHint=false), the description discloses operational traits the annotations cannot: per-call idempotency keys so retries return the same URL, 60-minute price lock, 30 orders/hour/IP rate limit, cart limits, and a catalog of error codes with recovery actions. It also states that no partial order is ever created, which is critical behavioral context for a mutating tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is long but front-loaded and organized under Args/Returns with clear error grouping, and nearly every sentence carries operational payload. The one weakness is that the Args section restates several field descriptions already present in the schema (e.g., icing_text, quantity range), which is mild redundancy rather than bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, multi-object ordering tool with rich annotations and an output schema, the description covers everything an agent needs: pre-flight checks, custom cake and economy workflows, error codes and remedies, and the fact that returned summary.delivery_type/date may differ from what was sent. Nothing material to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite the low schema-computed coverage, the description adds substantial meaning: the two mutually exclusive cart line shapes, the rule that lines can be mixed under one delivery fee, phone format examples (E.164 or local), location_type/type defaults, date semantics (Asia/Colombo, today-or-future), the currency allow-list, and the server-side substitution of quoted cake details. This is meaning well beyond field-level schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a precise verb+resource+outcome: 'Create a guest-checkout order on Kapruka and return a click-to-pay link.' It also names the defining scope (guest checkout, no account needed), which separates it cleanly from sibling tools like kapruka_track_order or kapruka_check_delivery.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes the agent to siblings and states preconditions: verify deliverability with kapruka_check_delivery per limited item before ordering, confirm custom cake status via kapruka_custom_cake_status ('quoted'), resolve cities via kapruka_list_delivery_cities, and send economy only after the customer agrees. It also states exclusions ('only place a custom cake order after the customer clearly accepted the quoted total', 'never retry with the same city').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.