Support

Create a checkout and place an order

View as Markdown

Create a checkout session with selected products, update it with buyer and payment details, complete the checkout, and retrieve the resulting order.

Overview

Use this Shopping API v1 workflow to create a checkout, select payment, accept agreements, complete the checkout session to place the order, and retrieve its details.

A checkout session moves through states (incomplete → ready_for_complete → completed) as you add required data. All write operations require shopping.checkout:execute scope. Order retrieval requires shopping.order:read scope.

Go to About the Shopping API for required headers and the checkout state machine.

Prerequisites

The following prerequisites are required before you can create a checkout and place an order:

  • at least one variant ID from the product catalog
  • a PAT with shopping.checkout:execute and shopping.order:read scopes
  • an eligible saved payment instrument on the GoDaddy account
  • jq and uuidgen for the curl examples

Go to Search the catalog to get a variant ID.

Authenticate

These examples use a $GODADDY_PAT with shopping.checkout:execute and shopping.order:read scopes.

Go to About the Shopping API for the full list of required scopes.

Create a checkout session

POST /v1/shopping/checkout-sessions creates a checkout session with one or more line items. Pass variant IDs from the catalog search results.

The following procedure creates a checkout session.

  • Create a session with a selected variant:

    export CREATE_IDEMPOTENCY_KEY="$(uuidgen)"
    CREATE_RESPONSE="$(curl --fail-with-body --silent --show-error -X POST "https://api.godaddy.com/v1/shopping/checkout-sessions" \
      -H "Authorization: Bearer $GODADDY_PAT" \
      -H "Request-Id: $(uuidgen)" \
      -H "Idempotency-Key: $CREATE_IDEMPOTENCY_KEY" \
      -H "Content-Type: application/json" \
      -d "$(jq -n --arg id "$VARIANT_ID" '{context:{currency:"USD"},line_items:[{item:{id:$id},quantity:1}]}')")"
    export SESSION_ID="$(jq -er '.id' <<<"$CREATE_RESPONSE")"
    export LINE_ITEM_ID="$(jq -er '.line_items[0].id' <<<"$CREATE_RESPONSE")"
    export PAYMENT_INSTRUMENT_ID="$(jq -er '.payment.instruments | (map(select(.selected == true))[0] // .[0]).id' <<<"$CREATE_RESPONSE")"
    export PAYMENT_HANDLER_ID="$(jq -er '.payment.instruments | (map(select(.selected == true))[0] // .[0]).handler_id' <<<"$CREATE_RESPONSE")"
    export PAYMENT_INSTRUMENT_TYPE="$(jq -er '.payment.instruments | (map(select(.selected == true))[0] // .[0]).type' <<<"$CREATE_RESPONSE")"

The response includes an id and initial status. Save the writable line items and returned payment instruments for later requests.

Go to Example responses for trimmed response examples.

Idempotency key

Always send a unique Idempotency-Key on POST /checkout-sessions.

If the request times out, retry the unchanged request with the same key. The server returns the existing session instead of creating a duplicate.

A status of incomplete means required fields are missing. A status of ready_for_complete means all required fields are present. Check messages[] in the response for specific missing-field details.

Review the checkout

GET /v1/shopping/checkout-sessions/{id} returns current line items, totals, saved payment instruments, messages, links, and required agreements.

The following procedure refreshes the checkout before an update or completion.

  • Retrieve the checkout and selected payment instrument:

    CHECKOUT_RESPONSE="$(curl --fail-with-body --silent --show-error \
      "https://api.godaddy.com/v1/shopping/checkout-sessions/$SESSION_ID" \
      -H "Authorization: Bearer $GODADDY_PAT" \
      -H "Request-Id: $(uuidgen)")"
    export PAYMENT_INSTRUMENT_ID="$(jq -er '.payment.instruments | (map(select(.selected == true))[0] // .[0]).id' <<<"$CHECKOUT_RESPONSE")"
    export PAYMENT_HANDLER_ID="$(jq -er '.payment.instruments | (map(select(.selected == true))[0] // .[0]).handler_id' <<<"$CHECKOUT_RESPONSE")"
    export PAYMENT_INSTRUMENT_TYPE="$(jq -er '.payment.instruments | (map(select(.selected == true))[0] // .[0]).type' <<<"$CHECKOUT_RESPONSE")"

Persist the checkout ID, writable line item, and selected instrument for later requests. Preserve the instrument's returned id, handler_id, and type.

The standalone Go examples read these values from SESSION_ID, LINE_ITEM_ID, PAYMENT_INSTRUMENT_ID, PAYMENT_HANDLER_ID, and PAYMENT_INSTRUMENT_TYPE.

Update the checkout

PUT /v1/shopping/checkout-sessions/{id} replaces the writable checkout state. Use it to select a saved payment instrument and resend all line items.

PUT is a full replace, not a merge. Include the complete line_items[] array and every product input on each update. Omitting a writable field clears its previous value.

Payment instruments must already exist on the GoDaddy account. If none is eligible, add one at GoDaddy payment methods and retrieve the checkout again. Set BUYER_FIRST_NAME, BUYER_LAST_NAME, BUYER_EMAIL, and BUYER_PHONE to the buyer's contact values before running the examples.

The following procedure selects a payment instrument.

  • Select a payment instrument and resend all line items:

    export UPDATE_IDEMPOTENCY_KEY="$(uuidgen)"
    UPDATE_RESPONSE="$(curl --fail-with-body --silent --show-error -X PUT "https://api.godaddy.com/v1/shopping/checkout-sessions/$SESSION_ID" \
      -H "Authorization: Bearer $GODADDY_PAT" \
      -H "Request-Id: $(uuidgen)" \
      -H "Idempotency-Key: $UPDATE_IDEMPOTENCY_KEY" \
      -H "Content-Type: application/json" \
      -d "$(jq -n \
        --arg line_id "$LINE_ITEM_ID" --arg variant_id "$VARIANT_ID" \
        --arg first "$BUYER_FIRST_NAME" --arg last "$BUYER_LAST_NAME" \
        --arg email "$BUYER_EMAIL" --arg phone "$BUYER_PHONE" \
        --arg instrument_id "$PAYMENT_INSTRUMENT_ID" --arg handler "$PAYMENT_HANDLER_ID" \
        --arg type "$PAYMENT_INSTRUMENT_TYPE" \
        '{context:{currency:"USD"},line_items:[{id:$line_id,item:{id:$variant_id},quantity:1}],buyer:{first_name:$first,last_name:$last,email:$email,phone_number:$phone},payment:{instruments:[{id:$instrument_id,handler_id:$handler,type:$type,selected:true}]}}')")"

After the update, check status:

  • If ready_for_complete, proceed to complete the checkout.
  • If incomplete, check messages[] for remaining required fields.
  • If required_agreements[] is present, include consent when completing.

Line item removal warning

If an item can't be priced at update time, the server removes it from line_items[] and attaches a messages[] entry with code: line_item_removed. Check for missing items before proceeding.

Configure products and fulfillment

Include one line_items[] entry for each selected variant. Set quantity for each entry and preserve its returned line-item id on updates.

Some variants expose an input_schema. Build line_items[].input from that schema and resend the input on every PUT request.

DataRequest location
Buyer contactbuyer.first_name, buyer.last_name, buyer.email, and buyer.phone_number
Product configurationline_items[].input
Shipping or pickupfulfillment.methods[] and its selected destination
Billing addresspayment.instruments[].billing_address
Saved payment selectionThe returned instrument id, handler_id, type, and selected: true

Do not assume every saved instrument is a card. Preserve the handler and type returned by the checkout.

Go to Shopping Checkout reference for the full input, fulfillment, payment, and address schemas.

Handle required agreements

Before completing, check the checkout response for required_agreements[]. Some purchases require the buyer to accept terms first.

Before completing:

  • Include each agreement with required: true in consent.agreement_types.
  • Record the buyer's acceptance time in agreed_at.

Missing or incomplete consent returns HTTP 400 with validation_error.

Example required_agreements[] in a checkout response:

{
  "required_agreements": [
    {
      "key": "api_services_purchase_agreement",
      "title": "API Services Purchase Agreement",
      "url": "https://www.godaddy.com/legal/agreements/api-services-purchase-agreement",
      "required": true
    }
  ]
}

Complete the checkout

POST /v1/shopping/checkout-sessions/{id}/complete completes a ready_for_complete session and creates its order. The request body must include payment. Include consent if the checkout has required_agreements[].

The following procedure completes the checkout.

  • Complete the session:

    export COMPLETE_IDEMPOTENCY_KEY="$(uuidgen)"
    export AGREED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
    REQUIRED_AGREEMENTS="$(jq -c '[.required_agreements[]? | select(.required == true) | .key]' <<<"$UPDATE_RESPONSE")"
    COMPLETE_BODY="$(jq -n \
      --arg instrument_id "$PAYMENT_INSTRUMENT_ID" --arg handler "$PAYMENT_HANDLER_ID" \
      --arg type "$PAYMENT_INSTRUMENT_TYPE" --argjson agreements "$REQUIRED_AGREEMENTS" \
      --arg agreed_at "$AGREED_AT" \
      '{payment:{instruments:[{id:$instrument_id,handler_id:$handler,type:$type,selected:true}]}} +
       (if ($agreements | length) > 0 then {consent:{agreement_types:$agreements,agreed_at:$agreed_at}} else {} end)')"
    COMPLETE_RESPONSE="$(curl --fail-with-body --silent --show-error -X POST "https://api.godaddy.com/v1/shopping/checkout-sessions/$SESSION_ID/complete" \
      -H "Authorization: Bearer $GODADDY_PAT" \
      -H "Request-Id: $(uuidgen)" \
      -H "Idempotency-Key: $COMPLETE_IDEMPOTENCY_KEY" \
      -H "Content-Type: application/json" \
      -d "$COMPLETE_BODY")"
    export ORDER_ID="$(jq -er '.order.id' <<<"$COMPLETE_RESPONSE")"

The completion examples build consent from the checkout's required agreements. Never hardcode agreement keys across products.

The standalone Go completion example reads the required agreement-key array from REQUIRED_AGREEMENTS_JSON and the retry-stable key from COMPLETE_IDEMPOTENCY_KEY.

{
  "payment": { "instruments": [{ "id": "$PAYMENT_INSTRUMENT_ID", "handler_id": "$PAYMENT_HANDLER_ID", "type": "$PAYMENT_INSTRUMENT_TYPE", "selected": true }] },
  "consent": {
    "agreement_types": ["api_services_purchase_agreement"],
    "agreed_at": "$AGREED_AT"
  }
}

When status is completed, order.id contains the order identifier and order.permalink_url links to the receipt.

Retrieve the order

GET /v1/shopping/orders/{id} returns order totals, line statuses, fulfillment data, and a receipt link. A new order might return 404 order_not_found while the read model updates.

The following procedure retrieves an order.

  • Get order detail:

    ORDER_FILE="$(mktemp)"
    delay=1
    for attempt in 1 2 3 4 5 6; do
      status="$(curl --silent --show-error -o "$ORDER_FILE" -w '%{http_code}' \
        "https://api.godaddy.com/v1/shopping/orders/$ORDER_ID" \
        -H "Authorization: Bearer $GODADDY_PAT" \
        -H "Request-Id: $(uuidgen)")"
      if [ "$status" = "200" ]; then break; fi
      code="$(jq -r '.messages[0].code // empty' "$ORDER_FILE")"
      if [ "$status" != "404" ] || [ "$code" != "order_not_found" ]; then
        jq . "$ORDER_FILE" >&2
        exit 1
      fi
      sleep "$delay"
      delay=$((delay < 4 ? delay * 2 : 4))
    done
    test "$status" = "200"
    ORDER_RESPONSE="$(cat "$ORDER_FILE")"
    rm -f "$ORDER_FILE"

Example responses

The following sections provide example responses for creating and completing checkout sessions.

Checkout session

POST /checkout-sessions returns 201 with a session object. An eligible saved instrument can make it immediately ready_for_complete:

{
  "id": "d9cf79e3-b39b-4e58-8f30-ddfe1619e969",
  "status": "ready_for_complete",
  "currency": "USD",
  "line_items": [
    {
      "id": "1",
      "item": { "id": "hosting-economyapi:1mo" },
      "quantity": 1,
      "totals": [
        { "type": "subtotal", "amount": 999 },
        { "type": "total", "amount": 999 }
      ]
    }
  ],
  "totals": [
    { "type": "subtotal", "amount": 999 },
    { "type": "total", "amount": 999 }
  ],
  "payment": {
    "instruments": [
      {
        "id": "payment-instrument-id",
        "handler_id": "com.godaddy.payments",
        "type": "card",
        "selected": true
      }
    ]
  },
  "required_agreements": [
    {
      "key": "universal_terms_and_conditions",
      "title": "Universal Terms of Service Agreement",
      "required": true,
      "url": "https://www.godaddy.com/legal/agreements/universal-terms-of-service-agreement"
    }
  ],
  "ucp": { "version": "2026-04-08" }
}

Completed checkout

POST /checkout-sessions/{id}/complete returns status: completed when payment succeeds. Use the numeric order.id to retrieve the order:

{
  "id": "d9cf79e3-b39b-4e58-8f30-ddfe1619e969",
  "status": "completed",
  "order": {
    "id": "2211390786",
    "permalink_url": "https://account.godaddy.com/receipts/view/2211390786"
  },
  "ucp": { "version": "2026-04-08" }
}

Common errors

Responsemessages[].codeCauseAction
200 with warningline_item_removedA line item could not be priced and was removed from the session.Re-check line_items[] before completion.
400payment_instrument_invalidThe selected payment profile is unavailable or ineligible.Retrieve the checkout and select an eligible instrument.
400validation_errorPOST /complete was called with missing or incomplete consent.agreement_types.Check the checkout's required_agreements[], collect buyer consent, and retry with consent included.
401—The PAT is missing, invalid, or expired.Generate or export a valid PAT.
403—The PAT lacks the required Shopping scope.Generate a PAT with shopping.checkout:execute and shopping.order:read.
422item_not_found, invalid_domain, invalid_term, unsupported_currencyThe request is valid JSON but cannot be processed.Correct the item or currency before retrying with a new idempotency key.
404order_not_foundA completed order is not visible in the read model yet.Retry the unchanged GET with bounded backoff.
429—Rate limit exceeded.Wait for the Retry-After header value, then retry.

Checkout reads after completion

After completion, GET /checkout-sessions/{id} might return 404 checkout_not_found. Keep the completion response and use its order.id for order retrieval. Go to About the Shopping API for error handling.

Verify the purchase

Confirm that completion returned status: completed and a numeric order.id. After the order becomes visible, verify its currency, total, line-item statuses, and receipt permalink.

Fulfillment events[] and expectations[] are optional. Process them when present; do not require one expectation per line item.

Agent & Automation Notes

PermissionsShopping Checkout, Shopping Orders
Scopesshopping.checkout:execute, shopping.order:read
Rate limitRate-limited per credential. Go to /docs/api-users/rate-limits for current values.
IdempotentNo
DestructiveYes — confirm before executing
On failureCompletion charges the selected instrument. Poll GET /orders/:orderId until the order becomes visible.

Last updated on

How is this guide?

On this page