Skip to main content
charge runs a recognized caller’s saved card. The caller is already known by phone number, so there is no Checkout Session to create and no link to text: you pass the amount, and Ringup charges the card and settles the money on the merchant’s own processor.
curl -X POST https://ringup.dev/api/tools/charge \
  -H "Content-Type: application/json" \
  -H "X-Caller-Number: +14155550142" \
  -H "X-Ringup-Merchant: tonys-pizza" \
  -H "X-Call-Id: call_abc123" \
  -d '{ "amount_cents": 8500, "description": "Front brake pads, 2022 Toyota Highlander" }'
Response
{
  "ok": true,
  "status": "succeeded",
  "payment_id": "pay_x",
  "order_id": "ord_x",
  "confirmation": "2PJJZY",
  "charged": { "brand": "VISA", "last_4": "5858", "amount_cents": 8500 }
}
amount_cents is the only required field. description and order_id are optional, and X-Call-Id keys idempotency so a retry within a call never double-charges. status is succeeded, failed, or pending; only succeeded moved money.

Only after the caller agrees, and only succeeded is true

Charge the card only after the caller verbally agrees to the amount. The result is ground truth: never tell the caller payment happened without a succeeded status and a payment_id. A failed status means nothing was charged, and pending means the money has not moved yet. Speak the confirmation code back only on succeeded.

Idempotent under retries

The charge is idempotent, keyed on the call and amount, so if the platform retries the tool call, the caller is charged once and the retry returns the original Payment. This is what makes it safe on platforms that auto-retry a function that does not answer fast enough.

With or without an order

  • With order_id, the Payment attaches to that order, so your system reconciles the two directly.
  • Without it, Ringup creates a minimal order to hang the Payment on, and echoes its id back so you still have something to match against.
Whether or not you pass one, your server gets the same checkout.completed webhook as its out-of-band record. If the caller has no saved card yet, use send_link instead; if you want Ringup to run the whole payment step for you, create a Checkout Session. Whether payment is required at all is the merchant’s policy.

Next steps

Webhooks

Your out-of-band source of truth for every charge.

Testing

The fixtures and cards to exercise a charge end to end.