---
title: "Paywall Topup Choice"
method: POST
path: "/api/payment/paywall-topup"
---

# Paywall Topup Choice

`POST /api/payment/paywall-topup`

Stamp the paywall door onto the pending SetupIntent (prepay-match test).

Called by the checkout form right before ``confirmSetup`` so the
``setup_intent.succeeded`` webhook — the single grant boundary — sees the
final choice. Metadata updates merge, so ``device_id`` / ``domain`` stay.
A stale SI (decline → refreshAfterDecline) is re-stamped on the next
submit because the form calls this on every attempt.

## Request body

- PaywallTopupRequest
  - `device_id` string, required
  - `topup_usd` integer, required

## Response `200`

Successful Response

- unknown

## Other responses

- `422` — Validation Error

## Changes

- **2026-09-04** `b33fc5cb0069` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/explee/apis/explee-api/changes/api/payment/paywall-topup/post.md)

---

[API](https://skmtc.dev/explee/apis/explee-api.md) · [All operations](https://skmtc.dev/explee/apis/explee-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/explee/explee-api/revisions/b33fc5cb0069/schema)
