---
title: Checkout
full: true
_openapi:
  toc:
    - depth: 2
      title: List or search merchants
      url: '#list-or-search-merchants'
    - depth: 2
      title: One merchant, with its catalogue when it has one
      url: '#one-merchant-with-its-catalogue-when-it-has-one'
    - depth: 2
      title: Price a cart, with shipping options, before anything is charged
      url: '#price-a-cart-with-shipping-options-before-anything-is-charged'
    - depth: 2
      title: The cards this user has vaulted
      url: '#the-cards-this-user-has-vaulted'
    - depth: 2
      title: Search products across the vetted merchant network
      url: '#search-products-across-the-vetted-merchant-network'
    - depth: 2
      title: Resolve a product URL into something buyable
      url: '#resolve-a-product-url-into-something-buyable'
    - depth: 2
      title: Place the order — this is the call that spends money
      url: '#place-the-order--this-is-the-call-that-spends-money'
    - depth: 2
      title: Onboard a merchant nobody has bought from before
      url: '#onboard-a-merchant-nobody-has-bought-from-before'
    - depth: 2
      title: Recent orders for the authenticated user
      url: '#recent-orders-for-the-authenticated-user'
    - depth: 2
      title: One order, with the failure contract
      url: '#one-order-with-the-failure-contract'
    - depth: 2
      title: Dispute-grade evidence bundle
      url: '#dispute-grade-evidence-bundle'
    - depth: 2
      title: Per-merchant success rate
      url: '#per-merchant-success-rate'
  structuredData:
    headings:
      - content: List or search merchants
        id: list-or-search-merchants
      - content: One merchant, with its catalogue when it has one
        id: one-merchant-with-its-catalogue-when-it-has-one
      - content: Price a cart, with shipping options, before anything is charged
        id: price-a-cart-with-shipping-options-before-anything-is-charged
      - content: The cards this user has vaulted
        id: the-cards-this-user-has-vaulted
      - content: Search products across the vetted merchant network
        id: search-products-across-the-vetted-merchant-network
      - content: Resolve a product URL into something buyable
        id: resolve-a-product-url-into-something-buyable
      - content: Place the order — this is the call that spends money
        id: place-the-order--this-is-the-call-that-spends-money
      - content: Onboard a merchant nobody has bought from before
        id: onboard-a-merchant-nobody-has-bought-from-before
      - content: Recent orders for the authenticated user
        id: recent-orders-for-the-authenticated-user
      - content: One order, with the failure contract
        id: one-order-with-the-failure-contract
      - content: Dispute-grade evidence bundle
        id: dispute-grade-evidence-bundle
      - content: Per-merchant success rate
        id: per-merchant-success-rate
    contents:
      - content: >
          Merchants already in the network. The `rail` decides what is possible:

          `shopify` merchants quote live prices and real shipping options and
          accept

          a delivery address; `worker` merchants price from a cached catalogue.

          `is_test` marks a store Agnic runs for testing — no real money moves
          there.
        heading: list-or-search-merchants
      - content: >
          Builds a live Storefront cart and returns what the order would
          actually

          cost, including the merchant's real delivery options. Charges nothing
          and

          launches no browser.


          Two amount semantics, and the difference matters: when
          `amount_is_final`

          is true the total is tax-inclusive and `expected_amount_minor` IS the

          charge. When it is false the merchant adds tax at checkout, and

          `expected_amount_minor` is a CEILING the real charge stays under.


          When the merchant offers more than one fulfilment option and none was

          chosen, `requires_fulfillment_choice` is true and
          `expected_amount_minor`

          is withheld — there is no honest amount to bind until the choice is
          made.
        heading: price-a-cart-with-shipping-options-before-anything-is-charged
      - content: >
          Card numbers never appear here and never reach Agnic's application
          code:

          vaulting happens straight into the vault from the browser. What comes

          back is what you need to choose between cards and nothing more.


          Omit `card_alias_id` on a dispatch and the default card is used.
        heading: the-cards-this-user-has-vaulted
      - content: >
          Finds a PRODUCT across thousands of vetted Shopify shops in one
          market.

          Read-only: it charges nothing and onboards nothing.


          Prices are BROWSE-TIME — what the catalogue last saw. `POST

          /api/autofill/shopify/quote` is the authoritative amount and the only

          one that accounts for shipping, tax and current stock.


          A result carrying `onboard` is at a shop Agnic has never bought from.

          That is normal and is most of the network: call

          `POST /api/autofill/explore` with that URL first, then quote.


          The whole approved pool is searched. The catalogue accepts at most
          1,000

          shops per call and every market is at that ceiling, so this chunks and

          merges rather than truncating — `chunks` says how many calls it took.
        heading: search-products-across-the-vetted-merchant-network
      - content: >
          Turns a product page URL into a `sku`, with the live storefront price
          and

          stock. Shopify shops only.


          **Send the URL exactly as the user copied it.** The `?variant=`
          parameter

          is which size or colour they chose. Without one this resolves the
          first

          available option and says so in `variant_note` — for a product whose

          options matter, ask the user to re-copy the link after choosing rather

          than picking for them.


          Read-only by design: it never onboards a merchant. A response carrying

          `onboard` needs `POST /api/autofill/explore` first. A GET that quietly

          created a merchant record would be a side effect nobody asked for.
        heading: resolve-a-product-url-into-something-buyable
      - content: >
          Creates the order and dispatches it. Returns immediately with an

          `order_id`; the checkout itself takes about a minute. Poll

          `GET /api/autofill/orders/{id}` until it is terminal. **Never call
          this

          twice for the same order.**


          `ship_to` and `constraints` must be IDENTICAL to the values used at

          preview. They are part of what the confirmation token binds, so any

          difference means nothing is charged — which is what stops a
          destination

          or a spending limit changing between approval and payment.


          A `202` with `approval_required` is not a failure: the purchase falls

          outside the user's standing signed policy and they must approve it
          with

          their passkey. Show the URL, poll the approval, then call again with

          `approval_token`.
        heading: place-the-order--this-is-the-call-that-spends-money
      - content: >
          Drives an unseen merchant's live checkout read-only, stops at the
          payment

          step, charges nothing, and records what an order there takes. Slow —
          allow

          up to two minutes. Returns an `order_id` of kind `explored`; poll it.
        heading: onboard-a-merchant-nobody-has-bought-from-before
      - content: |
          Poll this while an order is in flight. Once terminal it carries
          `retryable` and `retry_action`, which exist so you never have to
          pattern-match an error code.
        heading: one-order-with-the-failure-contract
      - content: >
          What was asked, what the user approved, the signed mandate chain, how
          the

          order was driven, the merchant's own response, and the delivery
          address in

          full. Built to be handed to a scheme months later.
        heading: dispute-grade-evidence-bundle
      - content: >
          Runs, successes and the resulting pass rate per merchant recipe.
          Orders

          placed at test stores are excluded by rule, so this number only ever

          reflects real purchases.
        heading: per-merchant-success-rate
---

{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}

Buy from merchants that never integrated with anything. Find a merchant, price an order with shipping known up front, place it with a vaulted card, and follow it to a named outcome. Preview never charges; only POST /api/autofill/dispatch spends money.


<APIPage document={"content/openapi/agnicpay.yaml"} operations={[{"path":"/api/autofill/merchants","method":"get"},{"path":"/api/autofill/merchants/{id}","method":"get"},{"path":"/api/autofill/shopify/quote","method":"post"},{"path":"/api/autofill/cards","method":"get"},{"path":"/api/autofill/products/search","method":"get"},{"path":"/api/autofill/products/lookup","method":"get"},{"path":"/api/autofill/dispatch","method":"post"},{"path":"/api/autofill/explore","method":"post"},{"path":"/api/autofill/orders","method":"get"},{"path":"/api/autofill/orders/{id}","method":"get"},{"path":"/api/autofill/orders/{id}/evidence","method":"get"},{"path":"/api/autofill/reliability","method":"get"}]} webhooks={[]} hasHead={true} />