Which API host?
Prefer the SDK on your server. The
proofable.me paths are the same contract, proxied for same-origin browser calls.
Lifecycle
- 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)orGET /api/v1/profile/gates/{gateId}onapi.proofable.me. - Eligibility:
GET /api/v1/proofs/check?gateId=...&address=...&includePrivate=true&includeQHashes=trueevaluates the visitor’s existing proofs against every requirement. An inline Gate Policy uses the same evaluator overPOST /api/v1/proofs/checkand collects no listing payment. - Verify: if proofs are missing, the visitor completes them (hosted verify link, VerifyGate, or
POST /api/v1/verificationfor signature-based verifiers). PassgateIdand reuse satisfied proofs viaoptions.reusedVerifierProofs. - 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. - Fulfill: deliver the reward with the verified
qHash(plus payment evidence for paid gates) viaclient.fulfillGate(...)orPOST /api/v1/gates/{gateId}/fulfill. If the snapshot includesrequestedAccess, also send the buyer-approvedaccessGrant(connected account + selected resource). Hosted checkout stamps that grant on the receipt. A configured return URL receivesgrantandreceiptset to the same proof ID. The listing owner then callsPOST /api/v1/proofs/composio/executewithgrantset 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 return403. For an AI service listing, also send the buyer’sserviceParameters(see AI service listings).
Reading the gate check
WhengateId 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 (requiresincludeQHashes=true). Pass it asoptions.reusedVerifierProofsonPOST /api/v1/verificationso 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 carriesmatch 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.
Verification links
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.
Paid gates
The snapshot’smonetization.charge describes pricing:
amountUsd,label,methods(usdc,stripe),cardPayoutReadyexecutionOrder:verifyThenCharge(default): verification completes first, then payment, then fulfill.
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.
- Stripe:
paymentCheckoutSessionIdfrom the checkout return. - USDC:
paymentTxHashof the on-chain transfer.
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 underserviceInputs (name, label, required). Send the buyer’s values as serviceParameters on fulfill:
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 aschedule (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 underpolicy.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
allRequiredSatisfiedand list them ingate.prerequisites. - Verification and fulfillment refuse a visitor who is missing one with
GATE_PREREQUISITE_MISSINGanddetails.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