One component. No server code.

You already built the thing. This is the whole of what it takes to start charging for it — a product ID, a button, and a callback that fires when the money has actually landed.

Dependencies
1
Server code
None
API keys
None
Terminal
npm install veyro-sdk
BuyButton.tsx
import { VeyroCheckout } from "veyro-sdk/react";

export function BuyButton() {
  return (
    <VeyroCheckout
      productId="your-product-id"
      onSuccess={(id) => unlock(id)}
    >
      Buy now — $25
    </VeyroCheckout>
  );
}

That is the integration. Everything below is detail, failure modes, and the version without the package.

1. What you need

A product with a price

Made on your Veyro dashboard. Its ID is what the button needs.

A guardian, if you are under 18

They complete the payment provider’s identity form once. The steps, in order.

That is it

No API keys, no webhook to set up, no server code. Veyro holds none of your customer’s card details and neither does your app.

2. Install it

Terminal
npm install veyro-sdk

3. Add the button

React, with the component:

React
import { VeyroCheckout } from "veyro-sdk/react";

export function BuyButton() {
  return (
    <VeyroCheckout
      productId="your-product-id"
      onSuccess={(transactionId) => {
        // The money has landed. Unlock the thing, send the file, show a receipt.
        console.log("paid", transactionId);
      }}
      onError={(error) => {
        console.error(error.message, error.fixPrompt);
      }}
    >
      Buy now — $25
    </VeyroCheckout>
  );
}

Anything else — Vue, Svelte, plain HTML — with the same function underneath:

Any framework
import { openCheckout } from "veyro-sdk";

document.querySelector("#buy").addEventListener("click", () => {
  openCheckout("your-product-id", {
    onSuccess: (transactionId) => { /* … */ },
    onError: (error) => console.error(error.message, error.fixPrompt),
  });
});

Call it inside the click, with no await before it. Checkout opens in a window, and a browser blocks a window opened after an await — which looks like the button doing nothing at all.

Without the SDK

The package is a convenience, not a requirement — it calls two public endpoints. This does the same job with no dependency, and works today whether or not the package is published.

Plain fetch
async function buy(productId) {
  const res = await fetch("https://withveyro.com/api/checkout/create", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ productId }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error);

  window.open(data.checkoutUrl, "_blank");

  // Ask every couple of seconds whether the payment has landed.
  for (;;) {
    await new Promise((r) => setTimeout(r, 2000));
    const s = await fetch(
      "https://withveyro.com/api/checkout/status?intent=" + data.intentId,
    ).then((r) => r.json());
    if (s.status === "completed") return s.transactionId;
  }
}

4. Check it before you ship

Paste this into your browser console, anywhere. It answers from Veyro, so it tells you about your product rather than about your code.

Browser console
await fetch("https://withveyro.com/api/integration-test", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ productId: "your-product-id" }),
}).then((r) => r.json()).then(console.log);

Every field is something the server can actually see. It cannot tell whether the package is installed in your project — nothing on our side can — so it does not pretend to.
readyToLaunch: true means a customer opening your link right now would get a payment form.

Connect your projectIntegration preview

Veyro is a REST API, so there is nothing to install. Paste the prompt below into the tool you built with and it will add a working checkout.

Two of the four are yours: the button that starts a checkout and the check that asks whether it was paid. Hover a stop for what it involves.

Where are you building?

Paste it into Claude Code, in the project you want to take payments. This only changes the instruction above — the prompt is the same, and Veyro has not tested these tools individually.


Add one and it goes straight into the prompt. Leave it blank and the prompt says where to put it.
Your integration prompt
Add Veyro payments to this project.

Veyro is a REST API. This prompt uses it directly, so there is nothing to
install. A veyro-sdk npm package also exists if you would rather use one.

1. Add a "Buy" button. When it is clicked, POST to:
   https://withveyro.com/api/checkout/create
   with JSON body: { "productId": "YOUR_PRODUCT_ID" }

2. The response is JSON:
   { "ok": true, "checkoutUrl": "...", "intentId": "..." }
   Send the customer to checkoutUrl. They pay there, on Veyro's hosted
   page, so no card details ever touch this project.

3. To find out whether they paid, GET:
   https://withveyro.com/api/checkout/status?intent=INTENT_ID
   Response: { "ok": true, "status": "pending" | "completed" | "refunded",
   "transactionId": "..." }
   Poll it after the customer returns, or check it when they land back on
   the site. "pending" is normal and means keep waiting.

4. On any error the response is { "ok": false, "code", "error", "fixPrompt" }.
   Show me the "error" text; do not invent your own message.

Rules:
- Do not store or handle card details anywhere in this project.
- Do not put any secret key in client-side code. These two endpoints need
  no key at all.
- Keep the product id in one place so it is easy to change.

Integration status

Add a product id above and run the test. Veyro checks what it can actually see from the server: whether the checkout opens, and whether a payment has ever arrived through Stripe’s signed webhook.

The two endpoints in the prompt are live now. The veyro-sdk package wraps them in a few lines of JavaScript if you would rather install something — the REST route above needs nothing installed and works either way.

5. Go live

There is no switch. Once that check comes back ready, the button takes real money. Your first payment appears in your wallet, and the wallet shows what has settled and what is still on its way.


If an AI tool is writing this for you

Copy one of these, fill in the brackets, and paste it in. They are written so the assistant changes the payment button and nothing else.

Claude Code, or Cursor
Add Veyro payments to my [framework] project.

- Install the SDK: npm install veyro-sdk
- Product ID: [paste it from your Veyro dashboard]
- Add a "Buy now" button on [which page]
- Import { VeyroCheckout } from "veyro-sdk/react" and use it for the button
- On successful payment, [what should happen]
- Keep the existing design and do not change anything else
- Follow the official docs at https://withveyro.com/docs/sdk
Lovable, or another in-browser builder
Add Veyro payments to this project using the npm package veyro-sdk.

- Add a button that opens Veyro checkout for product ID [paste it here]
- Handle both the success and the error callback
- Show the customer something after a successful payment
- Do not change the rest of the design
When something is not working
Veyro checkout is not working in my app. The error is:

[paste the whole error, including the fixPrompt if there is one]

Read https://withveyro.com/docs/sdk and fix only what that error points at.

When something goes wrong

Every refusal comes back with a code, a sentence in plain words, and a fixPrompt you can act on or paste back into whatever wrote the integration. This table is generated from the same source the API answers from, so it cannot fall out of date.

CodeWhat it meansWhat to do
product_not_foundNo product with that ID.The product ID does not match anything on Veyro. Open your Veyro dashboard, copy the ID from the product row, and replace the one in the code.
product_not_liveThat product is a draft, so it cannot take a payment yet.The product exists but is not published. Open your Veyro dashboard, edit the product and set its status to Live. The checkout link does not change when you do.
price_not_setThat product has no price.Open your Veyro dashboard, edit the product and give it a price. Nothing can be charged until there is an amount to charge.
price_below_minimumThat price is below what a card network will process.Card payments have a minimum of roughly $0.50. Edit the product on your Veyro dashboard and raise the price above it.
payments_not_set_upThis account cannot take payments yet.Payment setup is not finished. If you are under 18 this is your guardian's step: invite them from your Veyro dashboard, and they complete Stripe's identity form as themselves. Nothing can be charged until Stripe has accepted them.
no_product_idNo product ID was sent.The call reached Veyro without a productId. Check that the productId prop is set and is not undefined when the button is clicked.
rate_limitedToo many attempts from here. Wait a moment.Checkout is being started more often than a person could click. Make sure the checkout call runs inside the click handler and not on every render.
not_configuredPayments are not configured on this server.This one is ours, not yours. Email withveyro@gmail.com and we will look.
stripe_unavailableWe could not reach the payment provider. Nothing has been charged.A temporary problem between Veyro and Stripe. Try again in a moment; if it keeps happening, email withveyro@gmail.com.

Where the card details go

Not to your app, and not to your server. The button opens Veyro’s own checkout page, and the card form on it belongs to Stripe. Your site never receives a card number, which is why this package needs no keys and asks for no configuration.

The payment goes straight to your Stripe account. Veyro is never in the path of the money. How that works