Skip to content

Square

Setup guide for the square payments provider. The shared API (initiate_payment, verify_payment, refund_payment, webhooks, hooks, saved methods) is documented in Payments.

1. Get credentials. In the Square Developer Dashboard, create an application and copy the Access Token (sandbox or production) and the Location ID (Locations tab).

2. Configure the instance and secrets. In kirak.json:

"square": {
"type": "square",
"location_id": "...",
"environment": "sandbox",
"webhook_notification_url": "https://your-domain.com/payments/webhook/square"
}

environment is sandbox (the default) or production. In the environment:

Terminal window
KIRAK_PAYMENT_SQUARE_ACCESS_TOKEN=...
KIRAK_PAYMENT_SQUARE_WEBHOOK_SIGNATURE_KEY=... # from step 3

webhook_notification_url must be set and must exactly match the URL you register with Square – Square’s signature is computed over notification_url + raw_body, so a mismatch fails every verification.

3. Configure the webhook. Under your application -> Webhooks -> Add Endpoint, use the same URL as webhook_notification_url and select at minimum: payment.created, payment.updated, order.updated, refund.created, refund.updated, subscription.created, subscription.updated. refund.updated reports a refund that settled after it was requested; without it a refund stays unrecorded. To use saved cards, also select card.disabled and card.forgotten – they keep payment_methods in sync when a card is removed at Square (e.g. from the Square Dashboard) instead of through detach_payment_method – and card.updated and card.automatically_updated, which keep a saved card’s display fields (brand, last 4, expiry) current when the card is reissued. Copy the Signature Key into KIRAK_PAYMENT_SQUARE_WEBHOOK_SIGNATURE_KEY.

4. Use it:

# One-time payment -- creates a Square order + payment link
result = await kirak.payments.initiate_payment({
"provider": "square",
"user_id": "42", "amount": 2999, "currency": "GBP", # pence
"name": "Pro Plan", "type": "one_time",
})
# Subscription -- note the different param name: subscription_plan_variation_id,
# not subscription_plan_id (create the plan variation in Square Dashboard first)
result = await kirak.payments.initiate_payment({
"provider": "square",
"user_id": "42", "amount": 0, "currency": "GBP",
"name": "Pro Plan", "type": "subscription",
"subscription_plan_variation_id": "SQVARIATION123",
})

One seller account, several Kirak databases: a checkout payment is matched by its Square order id, which only the database that made it holds. An off-session charge’s reference_id is kirak-<row id>-<16 random hex>, and the random part is kept in the row’s payment_meta (kirak_ref), so another database’s payment for its own row with the same id is acknowledged and left alone. A kirak-<row id> reference from before this change is matched by id, but only to a row from before it too (one without a kirak_ref).

Known quirk: the default currency when a caller omits "currency" is GBP; always pass "currency" explicitly. refund_payment also defaults an unspecified refund currency to GBP regardless of your actual location.

after_webhook receives these provider-neutral event names (see Webhook Hooks):

data["event"] Gateway events
payment_completed payment.created or payment.updated with status COMPLETED
payment_failed payment.created or payment.updated with status FAILED (not for an off-session charge left REQUIRES_ACTION, which stays recoverable)
subscription_updated subscription.created, subscription.updated
refund_completed refund.created or refund.updated with status COMPLETED
payment_method_removed card.disabled, card.forgotten

Square reports payment.completed, payment.failed or refund.completed as the event_type of a payment or refund webhook, chosen from its status, and keeps Square’s own name in square_event_type. A payment that is APPROVED, PENDING or CANCELED, a refund that is PENDING, REJECTED or FAILED, and order.updated all report event = None.