Pay with Clear: API reference
Generated from @clear/public-api-contracts for version 2026-10-16. Base URL https://api.useclear.org.
Every request
Authorization: Bearer <key>. The secret key (clear_sk_…) from a server; the publishable key (clear_pk_…) only where a route says so.Clear-Version: 2026-10-16. Without it, the key's pinned version is used, and said in the answer. An unknown version is refused.Idempotency-Keyon the routes marked so: the same key and body give the same answer; the same key with another body is refused.- Bodies are JSON. Amounts are integer cents in
usd. Times are ISO 8601. Lists are newest first:{ object: "list", data, hasMore }, continued withstartingAfter. - A test key sees only test objects, and a live key only live ones.
Routes
POST /v1/paymentsIdempotency-KeyGET /v1/paymentsGET /v1/payments/:idPOST /v1/payments/:id/cancelGET /v1/pricesPOST /v1/payment_linksPOST /v1/refundsIdempotency-KeyPOST /v1/webhook_endpointsGET /v1/webhook_endpointsDELETE /v1/webhook_endpoints/:idGET /v1/webhook_deliveriesPOST /v1/modal_sessionsPOST /v1/payments
Make a payment for an amount your server worked out. Hand the page its clientSecret.
GET /v1/payments
Payments, newest first: by reference, or in a time range.
GET /v1/payments/:id
One payment.
POST /v1/payments/:id/cancel
Cancel a payment nobody has paid yet.
GET /v1/prices
The prices made in the merchant app, for Clear(key).attach(…, { price }) with no server.
POST /v1/payment_links
A payment link (pay.useclear.org/l/…), for an amount or a price. No website needed.
POST /v1/refunds
Refund a card payment, in part or in full. With requireApproval, it waits for an owner or manager in the merchant app. A Clear payment is refunded from Charges in the merchant app (refund_in_app).
POST /v1/webhook_endpoints
Where Clear sends events. The answer carries the signing secret, once.
GET /v1/webhook_endpoints
Your webhook endpoints, in this key’s mode.
DELETE /v1/webhook_endpoints/:id
Turn an endpoint off for good. What it was sent stays in the log.
GET /v1/webhook_deliveries
Each event sent to each endpoint: whether it got there, and the endpoint’s last answer. Newest first.
POST /v1/modal_sessions
What @useclear/js calls from the page to open the modal. Only from a website on your list in Developers.
Requests
CreatePayment
amountcurrencyusdreferencelineslines[].namelines[].amountlines[].quantity1methodsclear, card (at least 1)["clear","card"]metadataListPayments
referencecreatedFromcreatedTolimit20startingAfterpay_…)CreatePaymentLink
Either:
amountnoteexpiresAtallowOverTimefalseOr:
priceprice_…)quantity1noteexpiresAtallowOverTimefalseCreateRefund
paymentpay_…)amountreasonrequireApprovalfalseCreateWebhookEndpoint
urleventspayment.succeeded, payment.failed, payment.canceled, refund.succeeded (at least 1)CreateModalSession
Either:
priceprice_…)quantity1accentlogolocalemethodsclear, card (at least 1)emailOr:
paymentaccentlogolocalemethodsclear, card (at least 1)emailListWebhookDeliveries
endpointwe_…)statuspending, succeeded, failedlimit20startingAfterwhd_…)Objects
Payment
idpay_…)objectpaymentlivemodeamountcurrencyusdlineslines[].namelines[].amountlines[].quantityreferencemethodsclear, card (at least 1)statusrequires_customer, processing, succeeded, failed, canceledmethodclear, card, or nullamountRefundedclientSecretcreatedAtsucceededAtmetadataPrice
idprice_…)objectpricenameamountactiveallowQuantityPaymentLink
idplink_…)objectpayment_linklivemodeurlslugamountpriceprice_…), or nullquantitynoteexpiresAtallowOverTimeactivecreatedAtRefund
idre_…)objectrefundlivemodepaymentpay_…)amountstatuspending_approval, pending, succeeded, failed, canceledreasoncreatedAtWebhookEndpoint
idwe_…)objectwebhook_endpointlivemodeurleventspayment.succeeded, payment.failed, payment.canceled, refund.succeeded (at least 1)statusenabled, disabledsecretcreatedAtEvent
A webhook's body. type is one of payment.succeeded, payment.failed, payment.canceled, refund.succeeded; data is the payment (or for a refund event, the refund).
Either:
idevt_…)objecteventcreatedAtlivemodeapiVersion2026-10-16typepayment.succeededdatadata.idpay_…)data.objectpaymentdata.livemodedata.amountdata.currencyusddata.linesdata.lines[].namedata.lines[].amountdata.lines[].quantitydata.referencedata.methodsclear, card (at least 1)data.statusrequires_customer, processing, succeeded, failed, canceleddata.methodclear, card, or nulldata.amountRefundeddata.createdAtdata.succeededAtdata.metadataOr:
idevt_…)objecteventcreatedAtlivemodeapiVersion2026-10-16typepayment.faileddatadata.idpay_…)data.objectpaymentdata.livemodedata.amountdata.currencyusddata.linesdata.lines[].namedata.lines[].amountdata.lines[].quantitydata.referencedata.methodsclear, card (at least 1)data.statusrequires_customer, processing, succeeded, failed, canceleddata.methodclear, card, or nulldata.amountRefundeddata.createdAtdata.succeededAtdata.metadataOr:
idevt_…)objecteventcreatedAtlivemodeapiVersion2026-10-16typepayment.canceleddatadata.idpay_…)data.objectpaymentdata.livemodedata.amountdata.currencyusddata.linesdata.lines[].namedata.lines[].amountdata.lines[].quantitydata.referencedata.methodsclear, card (at least 1)data.statusrequires_customer, processing, succeeded, failed, canceleddata.methodclear, card, or nulldata.amountRefundeddata.createdAtdata.succeededAtdata.metadataOr:
idevt_…)objecteventcreatedAtlivemodeapiVersion2026-10-16typerefund.succeededdatadata.idre_…)data.objectrefunddata.livemodedata.paymentpay_…)data.amountdata.statuspending_approval, pending, succeeded, failed, canceleddata.reasondata.createdAtModalSession
idms_…)objectmodal_sessionlivemodeurlexpiresAtErrorResponse
errorerror.typeinvalid_request, authentication, permission, not_found, conflict, rate_limit, apierror.codeparameter_missing, parameter_invalid, parameter_unknown, amount_too_small, amount_too_large, lines_exceed_amount, metadata_invalid, quantity_not_allowed, partial_refund_unsupported, refund_exceeds_payment, webhook_url_invalid, idempotency_key_required, version_unknown, key_missing, key_invalid, key_expired, publishable_key_not_allowed, origin_not_allowed, method_unavailable, payment_not_found, price_not_found, payment_link_not_found, refund_not_found, webhook_endpoint_not_found, route_not_found, idempotency_key_reused, reference_taken, price_inactive, payment_link_inactive, payment_link_expired, payment_not_cancelable, payment_not_refundable, payment_closed, refund_in_app, rate_limited, internal_errorerror.messageerror.paramWebhookDelivery
idwhd_…)objectwebhook_deliverylivemodeendpointwe_…)eventevent.idevt_…)event.typepayment.succeeded, payment.failed, payment.canceled, refund.succeededstatuspending, succeeded, failedattemptsresponseStatuslastAttemptAtnextAttemptAtcreatedAtErrors
Every refusal is { "error": { "type", "code", "message", "param" } }. Branch on code; message is for people; param is the field at fault.
parameter_missingparameter_invalidparameter_unknownamount_too_smallamount_too_largelines_exceed_amountmetadata_invalidquantity_not_allowedpartial_refund_unsupportedrefund_exceeds_paymentwebhook_url_invalididempotency_key_requiredversion_unknownkey_missingkey_invalidkey_expiredpublishable_key_not_allowedorigin_not_allowedmethod_unavailablepayment_not_foundprice_not_foundpayment_link_not_foundrefund_not_foundwebhook_endpoint_not_foundroute_not_foundidempotency_key_reusedreference_takenprice_inactivepayment_link_inactivepayment_link_expiredpayment_not_cancelablepayment_not_refundablepayment_closedrefund_in_apprate_limitedinternal_errorLists
- Versions:
2026-10-16 - Payment statuses:
requires_customer,processing,succeeded,failed,canceled - Refund statuses:
pending_approval,pending,succeeded,failed,canceled - Webhook delivery statuses:
pending,succeeded,failed