Shopify Integration
Zazu doesn't yet ship a native Shopify Payments app. In the meantime, several merchants run Zazu alongside Shopify using the patterns below.
What works today#
You can accept card payments for Shopify orders, with one constraint: the buyer leaves the Shopify checkout page to pay on a Zazu-hosted page. Once payment completes, you reconcile the Shopify order with a webhook.
- Checkout Sessions API — server-created, one-off, expire in 30 minutes by default. Best fit for cart checkout.
- Payment Links API — single-use or reusable URLs you email or SMS to a buyer. Best fit for manual invoicing.
- Webhooks — checkout_session.completed and payment_link.paid events for reconciliation.
Which pattern fits you?#
- Pattern A — Post-purchase redirect. In-house engineering; cleanest buyer experience without a Payments App. A custom Shopify app subscribes to orders/create, calls POST /api/checkout_sessions server-side, then sends the buyer the returned url (email/SMS, or a Plus post-purchase checkout extension).
- Pattern B — Workflow automation (no-code). Trigger on Shopify's orders/create in n8n/Zapier/Make, create a checkout session, email/SMS the url, mark the order paid on checkout_session.completed. Simpler to build; higher abandonment than A.
- Pattern C — Standalone Payment Links. Direct sales (Instagram/WhatsApp/in-person) with Shopify as catalog only. Create a payment link per product and send it through your usual channels.
Example: create a checkout session from your Shopify app#
POST /api/checkout_sessions
The metadata.shopify_order_id is echoed back in the checkout_session.completed webhook — use it to look up the Shopify order and mark it paid via the Shopify Admin API. completed fires the moment the buyer's payment is confirmed (the session then reads clearing until the provider settles); wait for checkout_session.settled instead only if your flow must not run before funds have actually landed.
curl -X POST "https://zazu.africa/api/checkout_sessions" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"account_id": "01964a3b-0000-7000-8000-ac6000000a01",
"amount": 1500.00,
"success_url": "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://your-shop.myshopify.com/cart",
"metadata": { "shopify_order_id": "5142318973029" },
"description": "Order #1042"
}'zazu checkout-sessions create \
--account-id 01964a3b-0000-7000-8000-ac6000000a01 \
--amount 1500.00 \
--success-url "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}" \
--cancel-url "https://your-shop.myshopify.com/cart"import { Zazu } from "@getzazu/sdk";
const zazu = new Zazu({ apiKey: process.env.ZAZU_API_KEY });
await zazu.checkoutSessions.create({
account_id: "01964a3b-0000-7000-8000-ac6000000a01",
amount: "1500.00",
success_url: "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
cancel_url: "https://your-shop.myshopify.com/cart",
metadata: { shopify_order_id: "5142318973029" },
});require "zazu"
zazu = Zazu.new(api_key: ENV["ZAZU_API_KEY"])
zazu.checkout_sessions.create(
account_id: "01964a3b-0000-7000-8000-ac6000000a01",
amount: "1500.00",
success_url: "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
cancel_url: "https://your-shop.myshopify.com/cart",
metadata: { shopify_order_id: "5142318973029" }
)from zazu_sdk import Zazu
client = Zazu(api_key="sk_live_...")
client.checkout_sessions.create(
account_id="01964a3b-0000-7000-8000-ac6000000a01",
amount="1500.00",
success_url="https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
cancel_url="https://your-shop.myshopify.com/cart",
metadata={"shopify_order_id": "5142318973029"},
)import zazu "github.com/getzazu/zazu-go"
client, _ := zazu.New(zazu.WithAPIKey(os.Getenv("ZAZU_API_KEY")))
session, err := client.CheckoutSessions.Create(ctx, zazu.Attributes{
"account_id": "01964a3b-0000-7000-8000-ac6000000a01",
"amount": "1500.00",
"success_url": "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://your-shop.myshopify.com/cart",
"metadata": map[string]any{"shopify_order_id": "5142318973029"},
})let client = zazu_sdk::Client::builder()
.api_key(std::env::var("ZAZU_API_KEY")?)
.build()?;
let session = client.checkout_sessions().create(&serde_json::json!({
"account_id": "01964a3b-0000-7000-8000-ac6000000a01",
"amount": "1500.00",
"success_url": "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://your-shop.myshopify.com/cart",
"metadata": { "shopify_order_id": "5142318973029" },
}))?;{:ok, client} = Zazu.new(api_key: System.fetch_env!("ZAZU_API_KEY"))
{:ok, session} =
Zazu.CheckoutSessions.create(client, %{
"account_id" => "01964a3b-0000-7000-8000-ac6000000a01",
"amount" => "1500.00",
"success_url" => "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
"cancel_url" => "https://your-shop.myshopify.com/cart",
"metadata" => %{"shopify_order_id" => "5142318973029"}
})require "zazu"
client = Zazu::Client.new # reads ZAZU_API_KEY
session = client.checkout_sessions.create(
account_id: "01964a3b-0000-7000-8000-ac6000000a01",
amount: "1500.00",
success_url: "https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}",
cancel_url: "https://your-shop.myshopify.com/cart",
metadata: {shopify_order_id: "5142318973029"}
)use Zazu\Client;
$client = new Client(apiKey: getenv('ZAZU_API_KEY'));
$session = $client->checkoutSessions->create([
'account_id' => '01964a3b-0000-7000-8000-ac6000000a01',
'amount' => '1500.00',
'success_url' => 'https://your-shop.myshopify.com/account/orders?session={CHECKOUT_SESSION_ID}',
'cancel_url' => 'https://your-shop.myshopify.com/cart',
'metadata' => ['shopify_order_id' => '5142318973029'],
]);Reconciliation#
- Verify the webhook signature using the X-Zazu-Signature header.
- Look up the Shopify order via metadata.shopify_order_id (A/B) or payment_reference (C).
- Mark the order paid via the Shopify Admin API (orderMarkAsPaid mutation). checkout_session.completed is the payment confirmation — the session may still read clearing (settled_at null) until the provider settles and checkout_session.settled fires.
- Return 2xx within 10 seconds; Zazu retries non-2xx on the standard schedule.
Refunds: Zazu settles card payments directly into your bank account, so refunds aren't issued by Zazu or visible from the Shopify admin — you issue them from your bank.