harbordocs Get API keys

Checkouts

A checkout turns an offer into an order. Harbor builds the cart at the store, checks the user's rules against the real total, and tells you exactly what has to happen next.

Create a checkout

Create it from an offer, or straight from a product link. Both need the user's token.

curl
curl https://www.useharbor.io/v1/checkouts \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Harbor-User-Token: $USER_TOKEN" \
  -H "content-type: application/json" \
  -d '{
    "offer_id": "ofr_071f4m634y1x453v055k",
    "quantity": 1,
    "buyer": { "email": "sam@example.com" },
    "shipping_address": {
      "name": "Sam Shopper", "line1": "1 Test St", "city": "Chicago",
      "region": "IL", "postal_code": "60601", "country": "US"
    }
  }'
Field What it does
offer_id or product_url Exactly one. Use product_url for major retailers, whose prices are read in the user's browser.
item_ref A specific variant from the offer's variants. Defaults to the offer's own item_ref.
quantity 1 to 20.
buyer email and phone. Platform stores usually need an email.
shipping_address Two-letter country. Major retailers use the address saved in the user's account instead.

Statuses

Status Meaning What you do
building Harbor is creating the cart at the store. Wait.
requires_user_action Something has to happen before the order can be placed. Read next_action.
ready_to_confirm The total is known and within the user's rules. Call confirm.
confirming Harbor is placing the order. Wait.
completed The order was placed. order_id is set. Follow the order.
failed It can't go through. error says why. Show error.display_message to the user if present.
canceled You canceled it. Nothing.

Every change sends a checkout.updated webhook, plus a specific event for requires_user_action, completed and failed.

Next actions

When the status is requires_user_action, next_action.type tells you who does what.

Type Who What to do
confirm The user Open next_action.url. The user reviews the total and approves. The checkout then returns to ready_to_confirm and you call confirm.
user_input You or the user Provide next_action.fields. Address or email: call update. A code the store sent the user: call user input.
redirect_to_merchant The user Open next_action.url, the store's own checkout page. The user finishes there with one tap.
on_device The user's browser Major retailers. The Harbor extension is preparing the order; the user taps Place order in their browser. Wait for the webhook.
reconnect The user Their store connection needs attention. Send them through Approve again.

Each next_action has a plain-language description you can show as-is.

Confirm

When the total is at or above the user's confirm_above, or the price changed since the offer, requires_user_confirmation is true and the next action is confirm:

json
{
  "status": "requires_user_action",
  "requires_user_confirmation": true,
  "next_action": {
    "type": "confirm",
    "url": "https://www.useharbor.io/confirm/chk_2w3i5a4h…?t=…",
    "description": "This order is above the user's confirmation threshold."
  }
}

Open the URL for the user. If you opened it with window.open, Harbor posts { type: "harbor:confirmed", checkout_id, decision } back to your page when they answer. You'll also get a checkout.updated webhook with ready_to_confirm.

Update buyer details

If the store asks for an address or email (user_input with fields like shipping_address or buyer.email), send them and Harbor re-prices the cart:

curl
curl https://www.useharbor.io/v1/checkouts/chk_…/update \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Harbor-User-Token: $USER_TOKEN" \
  -H "content-type: application/json" \
  -d '{ "buyer": { "email": "sam@example.com" }, "shipping_address": { … } }'

A new total needs fresh confirmation if the user's rules call for it.

User input

Some stores send the user a verification code while placing the order. Ask the user for it and pass it on:

curl
curl https://www.useharbor.io/v1/checkouts/chk_…/user_input \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Harbor-User-Token: $USER_TOKEN" \
  -H "content-type: application/json" \
  -d '{ "fields": { "verification_code": "123456" } }'

Place the order

curl
curl -X POST https://www.useharbor.io/v1/checkouts/chk_…/confirm \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Harbor-User-Token: $USER_TOKEN" \
  -H "Idempotency-Key: confirm-chk_…"

With an Idempotency-Key, retrying after a timeout returns the first result instead of placing a second order. Confirm only works in ready_to_confirm; otherwise it returns USER_ACTION_REQUIRED. Harbor checks max_per_day again at this point. The response is the checkout, usually completed with an order_id. It can also come back requires_user_action (for example, a code from the store) or failed (for example, PAYMENT_DECLINED).

Cancel

curl
curl -X POST https://www.useharbor.io/v1/checkouts/chk_…/cancel \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Harbor-User-Token: $USER_TOKEN"

Any open checkout can be canceled. For major retailers this also stops the work in the user's browser.

What Harbor guarantees

  • An order is only placed when the user's rules allow it, or the user confirmed it themselves.
  • Rules are checked against the store's real total, including shipping and tax.
  • A price change since the offer always comes back to the user.
  • At major retailers, the final tap is always the user's.