Sell through the Checkout API

The Checkout API makes it possible to purchase products from a Shopify store programmatically. A checkout in Shopify is the object used to manage a customer’s cart as it transitions to a paid checkout. This includes calculating taxes, shipping rates, attaching the customer’s information, and finally completing a purchase by submitting a payment. Use this API if you want a fully customized checkout user experience, while taking full advantage of the commerce engine used to power every Shopify store.

Caution

The Checkout API is only for use with the Sales Channel SDK. It is not possible to use it to create a new checkout for an individual store — for that you can use our JavaScript, iOS, and Android Buy SDKs.

How it works

Using a series of API calls, your platform can create a checkout, and update it a few times to programatically execute Shopify's checkout process, pictured below:

Checkout api flow

Authentication

Authentication for the Checkout API is performed via OAuth. All requests to this API must include the permanent access token in an X-Shopify-Access-Token request header. For more information, please read the OAuth Documentation

POST /admin/checkouts.json HTTP/1.1
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Host: channelsrule.myshopify.com
Content-Type: application/json

Protocol and hostname

The Checkout API is accessible via the store’s {subdomain}.myshopify.com or the store’s primary domain using https only.

Reservation

Reservations are done on a per-checkout basis. For the duration of the reservation, the line items in the checkout will be reserved for the given checkout. The reservation is established just before the payment is processed, and is maintained either until payment fails, or the order is created. In the event that a line item is no longer available the call to /payments.json will fail.

Polling

Most operations on checkout will cause asynchronous recalculation; this requires the API consumer to poll until all attributes are updated. The checkout is still returned, but information such as prices, tax lines, and shipping rates might not be complete, until all available information is loaded. Polling is indicated through an HTTP 202 accepted response code, a Location header (indicating the URL to poll) and a Retry-After header that suggests an interval delay in seconds.

Checkout throttle polling

During large sales or other events when many checkouts are being created in a short period of time, actions that create checkout resources can be throttled. When this happens, you'll receive an HTTP 303 See Other response code and a Location header (which includes a URL that you can use to poll the resource). To view the status of a throttled checkout, perform a GET request on the URL provided in the Location header, and refer to the polling guidelines above. After the queue has been processed, you'll receive a payload indicating that processing is complete.

Creating a checkout

In order for a customer to be able to purchase a desired product variant, a checkout must be created. The checkout can be updated partially at any time with the information provided by the customer.

The checkout provides information like tax lines, shipping costs, shipping requirements and more. You can display this to the customer and use it to complete other checkout requirements like updating the shipping rate that the customer chooses.

Example request to create a checkout

POST /admin/checkouts.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "checkout":{
    "email": "john.smith@example.com",
    "line_items": [{
      "variant_id": 11184583431,
      "quantity": 1
    }],
    "shipping_address": {
      "first_name": "John",
      "last_name": "Smith",
      "address1": "126 York St.",
      "city": "Ottawa",
      "province_code": "ON",
      "country_code": "CA",
      "phone": "(123)456-7890",
      "zip": "K1N 5T5"
    }
  }
}

View Response

HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
Location: https://channelsrule.myshopify.com/admin/checkouts/f9604c3f13b35c7ba36932436310ef09.json
Retry-After: 1

{
  "checkout":{
    "created_at":"2016-03-18T13:21:39-04:00",
    "currency":"CAD",
    "customer_id":2475498631,
    "email":"john.smith@example.com",
    "location_id":null,
    "order_id":null,
    "requires_shipping":true,
    "reservation_time":300,
    "source_name":"1257344",
    "source_identifier":null,
    "source_url":null,
    "taxes_included":false,
    "token":"f9604c3f13b35c7ba36932436310ef09",
    "updated_at":"2016-03-18T13:21:39-04:00",
    "payment_due":"28.25",
    "payment_url":"https:\/\/elb.deposit.shopifycs.com\/sessions",
    "reservation_time_left":300,
    "subtotal_price":"25.00",
    "total_price":"28.25",
    "total_tax":"3.25",
    "attributes":[],
    "note":"",
    "order":null,
    "privacy_policy_url":"https:\/\/checkout.shopify.com\/10890068\/policies\/16561415.html",
    "refund_policy_url":"https:\/\/checkout.shopify.com\/10890068\/policies\/16561351.html",
    "terms_of_service_url":"https:\/\/checkout.shopify.com\/10890068\/policies\/16561479.html",
    "user_id":null,
    "web_url":"https:\/\/checkout.shopify.com\/10890068\/checkouts\/f9604c3f13b35c7ba36932436310ef09",
    "tax_lines":[
      {
        "price":"3.25",
        "rate":0.13,
        "title":"HST"
      }
    ],
    "line_items":[
      {
        "id":"5a022a40c46d1e19",
        "key":"5a022a40c46d1e19",
        "product_id":3669728775,
        "variant_id":11184596679,
        "sku":"RUBY-001",
        "vendor":"channelsrule",
        "title":"Ruby Girls Tee",
        "variant_title":"small",
        "taxable":true,
        "requires_shipping":true,
        "price":"25.00",
        "compare_at_price":"30.00",
        "line_price":"25.00",
        "properties":{

        },
        "quantity":1,
        "grams":200,
        "fulfillment_service":"manual",
        "applied_discounts":[

        ]
      }
    ],
    "gift_cards":[

    ],
    "shipping_rate":null,
    "shipping_address":{
      "id":3763006023,
      "first_name":"John",
      "last_name":"Smith",
      "phone":"(123)456-7890",
      "company":null,
      "address1":"126 York St.",
      "address2":null,
      "city":"Ottawa",
      "province":"Ontario",
      "province_code":"ON",
      "country":"Canada",
      "country_code":"CA",
      "zip":"K1N 5T5"
    },
    "credit_card":null,
    "billing_address":null,
    "discount":null
  }
}

Polling for shipping rates

When a checkout requires shipping, polling is required to associate the selected shipping method with a shipping rate. When shipping rates are not available polling is required, as indicated with the Retry-After and Location headers.

GET /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3/shipping_rates.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

View Response

HTTP/1.1 202 ACCEPTED
Content-Type: application/json; charset=utf-8
Location: https://channelsrule.myshopify.com/admin/checkouts/f9604c3f13b35c7ba36932436310ef09/shipping_rates.json
Retry-After: 1

{
  "shipping_rates": []
}

Once ready, a list of shipping rates is returned.

GET /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3/shipping_rates.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

View Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Location: https://channelsrule.myshopify.com/admin/checkouts/f9604c3f13b35c7ba36932436310ef09/shipping_rates.json
Retry-After: 1

{
  "shipping_rates": [
    {
      "handle": "shopify-GROUND-10.00",
      "price": "10.00",
      "title": "Ground",
      "checkout": {
        "total_tax": "35.00",
        "total_price": "28.25",
        "subtotal_price": "25.00"
      },
      "phone_required": false,
      "delivery_range": []
    }
  ]
}

Updating a checkout

During the checkout process, it’s possible to update the checkout with the data received from the customer. A validation, specific only to the fields that have changed, will be provided so you can give feedback to the customer that is updating their information. This is especially useful to assign the shipping rates, add line items, add gift cards, and so on.

Example request to update the line items

PATCH /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "checkout":{
    "line_items": [
      {
        "variant_id": 11184583431,
        "quantity": 1
      },
      {
        "variant_id": 11184596679,
        "quantity": 1
      }
    ]
  }
}

View Response

HTTP/1.1 202 ACCEPTED
Content-Type: application/json; charset=utf-8
Location: https://channelsrule.myshopify.com/admin/checkouts/f9604c3f13b35c7ba36932436310ef09.json
Retry-After: 1

{
  "checkout":{
    ...
    "line_items":[
      {
        "id":"d4afb7b2a7668ec7",
        "key":"d4afb7b2a7668ec7",
        "product_id":3669721031,
        "variant_id":11184583431,
        "sku":"HOOT-001",
        "vendor":"channelsrule",
        "title":"Graphic Owl Guys Tee",
        "variant_title":"small",
        "taxable":true,
        "requires_shipping":true,
        "price":"25.00",
        "compare_at_price":"30.00",
        "line_price":"25.00",
        "properties":{},
        "quantity":1,
        "grams":200,
        "fulfillment_service":"manual",
        "applied_discounts":[

        ]
      },
      {
        "id":"e01a627d3f611bdc",
        "key":"e01a627d3f611bdc",
        "product_id":3669728775,
        "variant_id":11184596679,
        "sku":"RUBY-001",
        "vendor":"channelsrule",
        "title":"Ruby Girls Tee",
        "variant_title":"small",
        "taxable":true,
        "requires_shipping":true,
        "price":"25.00",
        "compare_at_price":"30.00",
        "line_price":"25.00",
        "properties":{},
        "quantity":1,
        "grams":200,
        "fulfillment_service":"manual",
        "applied_discounts":[]
      }
    ],
    ...
  }
}

Example request to update the shipping line

PATCH /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "checkout":{
    "shipping_line": {
      "handle": "shopify-Standard%20Shipping-8.00"
    }
  }
}

View Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "checkout": {
    ...
    "shipping_line":{
      "handle":"shopify-Standard%20Shipping-8.00",
      "price":"8.00",
      "title":"Standard Shipping"
    }
    ...
  }
}

Card vaulting

To ensure customer confidentiality, we process transactions on credit cards by relying on a separate card vaulting endpoint. Your app submits the credit card to the vault, and the vault returns a payment session_id that your app can use to create a payment for the credit card.

For more information, you can read the Checkout API reference.

Example request to vault a credit card

POST /sessions HTTP/1.1
Host: https://elb.deposit.shopifycs.com
Content-Type: application/json
Accept: application/json

{
  "payment": {
    "amount": "100.00",
    "unique_token": "my-client-generated-idempotency-token",
    "credit_card":{
      "number": "1",
      "month": "12",
      "year": "2019",
      "verification_value": "123",
      "first_name":"John",
      "last_name":"Smith"
    }
  }
}

View Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "id":"east-44a400ef20b36e38f10b882cb7260796"
}

Completing the purchase

Direct payment

To complete the purchase, a payment must be created using the session_id created in the previous step. The request must also include the total price of the checkout as amount and a client-generated idempotency token as unique_token.

POST /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3/payments.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "payment": {
    "request_details": {
      "ip_address": "123.1.1.1",
      "accept_language": "en-US",
      "user_agent": "Chrome/54.0.2840.98"
    },
    "amount": "10.00",
    "session_id": "east-44a400ef20b36e38f10b882cb7260796",
    "unique_token": "my-client-generated-idempotency-token"
  }
}

View Response

HTTP/1.1 202 ACCEPTED
Content-Type: application/json; charset=utf-8
Location: https://channelsrule.myshopify.com/admin/checkouts/f9604c3f13b35c7ba36932436310ef09/payments/123456789.json
Retry-After: 1

{
  "payment" : {
    "id": 123456789,
    "unique_token": "my-client-generated-idempotency-token",
    "transaction": null
  }
}

Polling is mandatory to retrieve the status of the transaction processed through the merchant's payment gateway. When the asynchronous processing is completed, the following request returns the transaction associated with the payment request.

GET /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3/payments/123456789.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

View Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "payment" : {
    "id": 123456789,
    "unique_token": "my-client-generated-idempotency-token",
    "transaction": {
      ...
    }
  }
}

Complete free checkouts

A call to the complete action asynchronously claims the inventory and transforms the checkout into an order. When the asynchronous processing is completed, the following request returns the checkout and associated order.

POST /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3/complete.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "checkout": {
    "token": "0aff29a2c5ab826fe623ebf8588617b3",
    "order": null
  }
}

View Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Location: https://channelsrule.myshopify.com/admin/checkouts/f9604c3f13b35c7ba36932436310ef09.json
Retry-After: 1

{
  "checkout" : {
    "token": "f9604c3f13b35c7ba36932436310ef09",
    "order": {
      "id": 987654321,
      "name": "# 987654321",
      "status_url": "https://checkout.shopify.com/12345678/checkouts/f9604c3f13b35c7ba36932436310ef09/thank_you"
    }
    ...
  }
}

Handling errors

Validation errors

PATCH /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "checkout": {
    "email": "not a valid email"
  }
}

View Response

HTTP/1.1 422 OK
Content-Type: application/json; charset=utf-8

{
  "errors":  {
    "checkout":  {
      "email": [{"code": "invalid", "message": "is invalid", "options": {}}]
    }
  }
}

For a list of elements, the errors will be accessible by their 0-based index under the list. For example, when there is an error only on the second line item, the errors will be accessible under key "1" within the line_items key.

PATCH /admin/checkouts/0aff29a2c5ab826fe623ebf8588617b3.json HTTP/1.1
Host: channelsrule.myshopify.com
X-Shopify-Access-Token: d833234ea788000e7aba6af8b1b9a282
Content-Type: application/json

{
  "checkout":{
    "line_items": [
      {
        "variant_id": 11184583431,
        "quantity": 1
      },
      {
        "variant_id": 11184596679,
        "quantity": 255
      }
    ]
  }
}

View Response

HTTP/1.1 422 OK
Content-Type: application/json; charset=utf-8

{
  "errors": {
    "checkout": {
      "line_items": {
        "1": {
          "quantity": [{
            "code": "not_enough_in_stock",
            "message": "Not enough items available. Only 30 left.",
            "options": {
              "remaining": 30
            }
          }]
        }
      }
    }
  }
}