Skip to main content
A published listing is a reusable checkout. Visitors complete the checks you configured, pay if the listing has a price, and receive the reward you attached. Use the VerifyGate widget or the hosted checkout link for the usual path, and the contract below to mirror it from your own app or backend.

Which API host?

Prefer the SDK on your server. The proofable.me paths are the same contract, proxied for same-origin browser calls.

Lifecycle

  1. Snapshot: load the public gate with its requirements, price, schedule, and whether a reward exists. The secret reward value stays out of the snapshot. Use client.getGate(gateId) or GET /api/v1/profile/gates/{gateId} on api.proofable.me.
  2. Eligibility: GET /api/v1/proofs/check?gateId=...&address=...&includePrivate=true&includeQHashes=true evaluates the visitor’s existing proofs against every requirement. An inline Gate Policy uses the same evaluator over POST /api/v1/proofs/check and collects no listing payment.
  3. Verify: if proofs are missing, the visitor completes them (hosted verify link, VerifyGate, or POST /api/v1/verification for signature-based verifiers). Pass gateId and reuse satisfied proofs via options.reusedVerifierProofs.
  4. Pay: for paid gates, payment happens after verification by default (executionOrder: "verifyThenCharge"). Gates with a connected payout account settle through one Stripe checkout session, where the visitor picks card or crypto. Gates with a custom wallet settle by direct USDC on Base.
  5. Fulfill: deliver the reward with the verified qHash (plus payment evidence for paid gates) via client.fulfillGate(...) or POST /api/v1/gates/{gateId}/fulfill. If the snapshot includes requestedAccess, also send the buyer-approved accessGrant (connected account + selected resource). Hosted checkout stamps that grant on the receipt. A configured return URL receives grant and receipt set to the same proof ID. The listing owner then calls POST /api/v1/proofs/composio/execute with grant set to that proof ID. Proofable runs the tool as the buyer and never returns the buyer’s credential. Missing, revoked, or out-of-scope grants return 403. For an AI service listing, also send the buyer’s serviceParameters (see AI service listings).

Reading the gate check

When gateId is passed, the response carries a per-requirement data.gate block. gate.allRequiredSatisfied === true is the only signal that checkout is ready. Top-level eligible and matchedCount exist for criteria-only checks and must not be used as gate readiness on their own.
  • satisfiedVerifierIds / missingVerifierIds: which requirements existing proofs cover.
  • prerequisites: present when the listing requires prior listings. One { gateId, satisfied } row each. See Prior listings.
  • reusedVerifierProofs: verifierId → qHash map (requires includeQHashes=true). Pass it as options.reusedVerifierProofs on POST /api/v1/verification so satisfied checks are not re-run.
  • Re-run the gate check after every interactive step (OAuth grant, personhood session). An interactive step counts once this check confirms it.

Request-time vs proof-based rules

Each requirement carries match rows ({ path, op, value }). They are enforced at two different moments: Proof-based rows mean an existing proof may not satisfy a stricter gate. For example, a personhood proof created for a basic gate will not satisfy another gate that also requires claims.age_min ≥ 21. The visitor must complete the additional check. For wallet-risk gates, any proof-based row also requires policyVerified to be true. A failed risk check never satisfies a gate. In the gate builder, choose Verification link. The visitor pastes their own HTTPS URL; Proofable reads JSON from that URL or its conventional .json form and checks whether verified is true. The saved gate holds the portable match rows reference.type = url and resolved.verified = true, with no fetch targets or callbacks to configure. API clients can use other resolved.* output matches when a source exposes a different public JSON contract. Resolved-link proofs default to five-minute freshness, so checkout reads current source status. See Content ownership for the wire shape and resolver safeguards. The snapshot’s monetization.charge describes pricing:
  • amountUsd, label, methods (usdc, stripe), cardPayoutReady
  • executionOrder: verifyThenCharge (default): verification completes first, then payment, then fulfill.
Method semantics:
  • stripe: hosted Stripe Checkout (card). Available when the gate has a connected payout account.
  • usdc: direct on-chain USDC transfer on Base. The only method for custom-wallet payout gates.
Fulfill payment evidence:
  • Stripe: paymentCheckoutSessionId from the checkout return.
  • USDC: paymentTxHash of the on-chain transfer.
Payments are bound to one gateId + qHash pair and cannot be reused for another checkout (409 PAYMENT_ALREADY_USED).

Fulfillment result

fulfillment.delivery is one of access_granted, redirect, download, or reveal. The secret value appears only here, after verification (and payment) succeeded for the caller’s wallet. An AI service order returns access_granted with no value, because its answer arrives on the receipt. When the listing unlocks an existing proof, fulfill copies a stored body into the buyer wallet if one exists. A title-only proof (an agent identity, a handle) skips that copy and returns rewardProof pointing at the source with accessGranted: true. The buyer grant is written either way.

AI service listings

An AI service listing runs a job for each buyer and delivers the answer on the buyer’s receipt. The snapshot lists what the buyer fills in under serviceInputs (name, label, required). Send the buyer’s values as serviceParameters on fulfill:
Each value can be up to 512 characters. A missing required value returns 400 SERVICE_PARAMETER_REQUIRED, and a longer one returns 400 SERVICE_PARAMETER_TOO_LONG. The buyer receives the run’s answer and never sees the listing’s instructions. When the run finishes, the buyer’s receipt (the qHash you fulfilled) records the outcome. Read it as the buyer with client.getPrivateProof(qHash, wallet):
status is completed when the run delivered an answer and failed when it did not. A failed order carries no result. Until the run finishes, status holds an in-progress value such as pending, so poll the receipt until it reads completed or failed.

Campaign windows

Gates may carry a schedule (startsAt / endsAt). Outside the window, gate checks report the closed state and the server refuses verification and fulfillment (GATE_NOT_STARTED, GATE_ENDED).

Prior listings

A listing can require that the visitor already completed other listings: an earlier campaign, the listing that awards a badge, or any step in a series. The gate stores them under policy.prerequisites as [{ "gateId": "gate_season-1" }], up to five, all required. A prerequisite is met when the visitor’s wallet holds that listing’s completed checkout receipt. Proofable reads the gate link it stamps on the receipt at checkout, never a proof tag, so a visitor cannot claim a listing they did not complete. Revoking the receipt removes the qualification. A visitor who already completed this listing keeps qualifying if the seller adds a prerequisite later.
  • Gate checks fold prerequisites into allRequiredSatisfied and list them in gate.prerequisites.
  • Verification and fulfillment refuse a visitor who is missing one with GATE_PREREQUISITE_MISSING and details.missingGateIds, before any check runs or credit is spent.
  • Publishing refuses a prerequisite that was never published (GATE_PREREQUISITE_NOT_FOUND) or that requires this listing back (GATE_PREREQUISITE_CYCLE). A paused or ended prerequisite stays valid, since past visitors still hold its receipt.

Next

Pricing

Plans, credits, and who pays

Gates in the SDK

getGate, gateCheck, and fulfillGate

API overview

Full HTTP API surface

Verifier catalog

Every check a gate can require
Last modified on October 25, 2026