partner.villamarket.ai · GraphQL · MCP · v0.1.0

Villa Partner Commerce

Build an alternate shop on Villa Market fulfilment — the same model Ocado uses with Waitrose. You own the customer experience. Villa remains the grocer: catalog identity, branch price, stock, basket, order, payment, and vans.

Public host: https://partner.villamarket.ai

You never call Villa’s internal website APIs. This host is the only commerce surface partners use.


Surfaces

Path Role
GET / This guide
POST /graphql GraphQL
/mcp MCP (Streamable HTTP) for agents
GET /schema.graphql Download the SDL
GET /health Liveness

Auth

Every GraphQL and MCP call (except public docs) needs:

X-Partner-Key: <key we issue you>

The key maps to your partnerId and registered orderSource (stamped on quotes and orders).

Shopper-scoped operations (basket, quote, order, payment) also need the customer’s Cognito id token:

Authorization: Bearer <shopper idToken>

ownerId is always the bare Cognito sub from that token. Do not invent it.


Quickstart — GraphQL

curl -sS https://partner.villamarket.ai/graphql \
  -H 'Content-Type: application/json' \
  -H 'X-Partner-Key: YOUR_KEY' \
  -d '{
    "query": "query($cpr: ID!, $b: ID!) { product(cprcode: $cpr, branchCode: $b) { cprcode nameEn price { amount currency source } inventory { sellableQty listable } } }",
    "variables": { "cpr": "141660", "b": "1000" }
  }'

Nested price and inventory are the join win: one client query, branch- correct numbers. Never display a total that did not come from quote.


Quickstart — MCP (Cursor)

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "villa-partner": {
      "url": "https://partner.villamarket.ai/mcp",
      "headers": {
        "X-Partner-Key": "YOUR_KEY"
      }
    }
  }
}

Tools mirror GraphQL: search_products, get_product, get_inventory, get_basket, add_basket_line, set_basket_quantity, empty_basket, create_quote, apply_coupon, create_order, start_payment, get_order, list_orders, resolve_fulfilment.

Resources: villa://schema, villa://docs.


Checkout rules (non-negotiable)

  1. quote.grandTotal is the bill. Never sum line prices in your app.
  2. orderCreate omits payment. Payment is a separate paymentStart that returns a KBank widget / session payload. Card PAN never touches this API.
  3. Line prices must be present on order create or later payment says grandTotal is missing.
  4. Stock is not reserved at basket-add. Soft hold starts at order create.
  5. Until production go-live, include test in specialComment.

Discount field contract (coupons / shipping):
https://knowledge.villamarket.ai/reference/discount-fields


Identity keys

Key Meaning
cprcode Product identity everywhere
branchCode Fulfilment branch — price authority
basketId Server-side basket
orderId Minted then created

Order status is not a top-level enum. Read payment.isPaid and shipping.schedules[].pickingStatus.


Sandbox vs production

Sandbox Production
Host same (partner.villamarket.ai) same
Keys sandbox partner key production partner key
Orders specialComment contains test never test in prod
Payment KBank sandbox widget production merchant via Villa

Live money requires: partner key issued, Cognito app client for your redirect URIs, fulfilment branch resolve confirmed, payment + order webhooks registered.


Webhooks (partner → you)

Register a HTTPS endpoint. We POST HMAC-signed events when payment settles or order status moves (once Villa feeds us those events).

POST https://your.example/webhooks/villa-partner
X-Villa-Partner-Signature: sha256=<hex>
Content-Type: application/json
{
  "type": "payment.paid | order.status",
  "orderId": "…",
  "partnerId": "…",
  "payload": {},
  "ts": 1710000000
}

Until Villa HMAC webhooks exist, we fan out from sanctioned order polls.

Inbound (Villa → us, for our adapter):

POST https://partner.villamarket.ai/webhooks/villa/payment
POST https://partner.villamarket.ai/webhooks/villa/order-status

Go-live checklist


Support

Engineering vault (public contracts): https://knowledge.villamarket.ai
Ask for a partner key: contact Villa Market AI / partner onboarding.