Skip to main content
POST
/
guest-wallets
/
topups
Top up guest wallet
curl --request POST \
  --url https://xquik.com/api/v1/guest-wallets/topups \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: <content-type>' \
  --header 'Idempotency-Key: <idempotency-key>' \
  --data '
{
  "amount_minor": 123,
  "currency": "<string>"
}
'
import requests

url = "https://xquik.com/api/v1/guest-wallets/topups"

payload = {
"amount_minor": 123,
"currency": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>",
"Idempotency-Key": "<idempotency-key>"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {
Authorization: '<authorization>',
'Content-Type': '<content-type>',
'Idempotency-Key': '<idempotency-key>'
},
body: JSON.stringify({amount_minor: 123, currency: '<string>'})
};

fetch('https://xquik.com/api/v1/guest-wallets/topups', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://xquik.com/api/v1/guest-wallets/topups"

payload := strings.NewReader("{\n \"amount_minor\": 123,\n \"currency\": \"<string>\"\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
req.Header.Add("Idempotency-Key", "<idempotency-key>")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
{
  "account_required": true,
  "amount": {},
  "checkout_url": "<string>",
  "credits": "<string>",
  "expires_at": "<string>",
  "instructions": "<string>",
  "purchase_id": "<string>",
  "status_url": "<string>",
  "poll_after_seconds": 123,
  "requires_user_interaction": true,
  "status": "<string>",
  "wallet_id": "<string>"
}
Add credits to an existing guest wallet. The wallet keeps the same paid_reads key. This endpoint creates a one-use Stripe-hosted Payment Link only after the user confirms the amount. It does not charge the user.
Never call this endpoint automatically after a 402. Show the available option and amount, then wait for explicit user confirmation.
idempotency_key=$(uuidgen | tr '[:upper:]' '[:lower:]')
curl -X POST https://xquik.com/api/v1/guest-wallets/topups \
  -H "Authorization: Bearer xq_your_guest_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $idempotency_key" \
  -d '{"amount_minor": 2500, "currency": "usd"}' | jq
Keep the current guest key and store the new Idempotency-Key as a secret. Give only checkout_url to the user. After payment, poll status_url every poll_after_seconds with the same key. Stop when latest_purchase.status is no longer pending. Use usable to decide whether paid reads can run.

Headers

Authorization
string
required
Send the guest key as Bearer xq_your_guest_key_here.
Content-Type
string
required
Must be application/json.
Idempotency-Key
string
required
A new cryptographically random UUID v4. Reuse it only for an exact retry of this top-up request.

Body

amount_minor
integer
required
Confirmed USD amount in cents. Minimum 1000 and maximum 25000.
currency
string
required
Must be usd.

Response

account_required
boolean
Always false.
amount
object
Confirmed amount in minor units and usd currency.
checkout_url
string
One-use Stripe-hosted Payment Link for the user to open.
credits
string
Credits to grant after verified payment.
expires_at
string
Pending Payment Link expiry.
instructions
string
Required user interaction and polling guidance.
purchase_id
string
Guest purchase ID.
status_url
string
Guest wallet status URL.
poll_after_seconds
integer
Minimum polling delay. Always 2 while pending.
requires_user_interaction
boolean
Always true.
status
string
Initial top-up status. Normally pending.
wallet_id
string
Existing guest wallet ID.
{
  "account_required": false,
  "amount": { "amount_minor": 2500, "currency": "usd" },
  "checkout_url": "https://buy.stripe.com/example",
  "credits": "166666",
  "expires_at": "2026-07-13T13:00:00.000Z",
  "instructions": "Give checkout_url to the user. They must complete payment on Stripe. Never submit payment for them. After payment, poll status_url every poll_after_seconds until latest_purchase.status is no longer pending.",
  "poll_after_seconds": 2,
  "purchase_id": "gp_example",
  "requires_user_interaction": true,
  "status": "pending",
  "status_url": "https://xquik.com/api/v1/guest-wallets/status",
  "wallet_id": "gw_example"
}
This response never returns a new API key.
The response sends Cache-Control: no-store, private. An exact replay also sends Idempotent-Replayed: true.
Last modified on July 13, 2026