---
id: quickstart
title: Quickstart
summary: From zero to a test payment in five minutes.
faces: ["public", "agent"]
personalises: ["publishable_key", "effective_mode"]
section: shared
group: Get started
order: 10
next: ["collect", "api"]
---
# Quickstart

Take a test payment in a few minutes: choose your platform, then paste its code.

Before you start you need a publishable key from the console, and your page's origin added to the
integration's allowed origins. Test mode needs nothing switched on: a key that allows test mode takes
test payments straight away. Only the Server API panel needs a secret key, and that one never leaves
your server.

## Choose your platform

Already on Stripe? [Migrating from Stripe](/js/stripe-compatibility)

### Script tag

You need your publishable key and this page's origin allowed. Paste the tag, add a container, call
`collect()`.

```html run id=quickstart-html
<script src="https://js.ripper.dev/r.js" data-key="rip_pk_EXAMPLE-KEY_00000000abcZ"></script>
<div data-ripper-checkout></div>
<script>
  ripper.collect({ amount: 4200, currency: 'GBP' }).then(function (result) {
    console.log(result.status);
  });
</script>
```

Pay with the reserved test card `9000 0000 0000 0000`, any future expiry and any 3-digit security code.
The checkout shows its own paid confirmation, and `result.status` is `captured`.

Next: [collect() reference](/js/collect) · [Test cards](/js/test-cards)

### npm

You need your publishable key and this page's origin allowed. Same call, from the package.

```js run id=quickstart-npm
import { loadRipper } from 'ripperpay';
const ripper = await loadRipper({ key: 'rip_pk_EXAMPLE-KEY_00000000abcZ' });
const result = await ripper.collect({ amount: 4200, currency: 'GBP' });
```

Pay with `9000 0000 0000 0000`. `result.success` is true and `result.status` is `captured`.

Next: [Script tag and loader](/js/script-tag) · [Test cards](/js/test-cards)

### React

You need your publishable key and this page's origin allowed.

```tsx id=quickstart-react
import { RipperCheckout } from 'ripperpay/react';

export function Checkout() {
  return (
    <RipperCheckout
      publishableKey="rip_pk_EXAMPLE-KEY_00000000abcZ"
      amount={4200}
      currency="GBP"
      onSuccess={(result) => console.log('paid', result.paymentId)}
      onError={(error) => console.log('not paid', error.code)}
    />
  );
}
```

Pay with `9000 0000 0000 0000`. `onSuccess` fires with the payment id.

Next: [React](/js/react) for every prop · [Test cards](/js/test-cards)

### Next.js

You need your publishable key and this page's origin allowed. Render the checkout from a client
component; `ripperpay` itself is safe to import on the server.

```tsx id=quickstart-nextjs
'use client';
import { RipperCheckout } from 'ripperpay/react';

export default function Pay() {
  return (
    <RipperCheckout
      publishableKey="rip_pk_EXAMPLE-KEY_00000000abcZ"
      amount={4200}
      currency="GBP"
      onSuccess={(result) => console.log('paid', result.paymentId)}
      onError={(error) => console.log('not paid', error.code)}
    />
  );
}
```

Pay with `9000 0000 0000 0000`. `onSuccess` fires with the payment id.

Next: [Next.js](/js/nextjs) · [Test cards](/js/test-cards)

### Server API

You need a secret key with the `create_payments` permission, read from an environment variable. It is for
your server only: never put it in a page, an app or a repository. Create the session on your server, then
hand the session to the browser. An amount your server set counts as a verified amount.

```bash id=quickstart-server-create
curl https://api.ripper.dev/v1/checkout/sessions \
  -H "X-Ripper-Api-Key: $RIPPER_SECRET_KEY" \
  -H "Rip-Idempotency-Key: order-1042" \
  -H "Content-Type: application/json" \
  -d '{"amount": 4200, "currency": "GBP", "order_reference": "ORDER-1042"}'
```

The response carries `id`, `client_secret` and `expires_in_seconds`. Send those to your page and pass them
to the checkout, which then uses your session instead of creating one:

```js id=quickstart-server-collect
const session = await fetch('/api/checkout-session').then((r) => r.json());
const result = await ripper.collect({ session });
```

Pay with `9000 0000 0000 0000`. Read the outcome on your server from the session or the payment, not from
the browser. Never log or store the `client_secret`.

Next: [Checkout sessions](/api/checkout-sessions) · [Webhooks](/api/webhooks)

### AI coding assistant (Claude Code, Codex, Cursor)

You need your publishable key. Paste this prompt into your assistant:

```text id=quickstart-ai-prompt
Read https://docs.ripper.dev/llms-full.txt before writing any code (https://docs.ripper.dev/llms.txt is its index).
Add a ripper checkout to this project with my publishable key rip_pk_EXAMPLE-KEY_00000000abcZ — never a secret key.
Take a £42.00 test payment with ripper.collect({ amount: 4200, currency: 'GBP' }), pay with the reserved test card 9000 0000 0000 0000 (any future expiry, any 3-digit security code), and show me the result.
```

These docs publish `/llms.txt` and `/llms-full.txt` for agents.

## Before the runtime loads

Every member of `ripper` works before the runtime has loaded — calls queue and replay in order.
`setEmail()` provides the shopper's email, so the checkout does not ask for it:

```js run id=quickstart-queue
ripper.setEmail('shopper@example.test');
ripper.init({ channel: 'web' });
const traceId = ripper.getTraceId(); // 'rip_sess_…', available as soon as the script loads
const result = await ripper.collect({ amount: 4200, currency: 'GBP' });
```

## A strict Content-Security-Policy

If your page sends one, the checkout needs a few hosts allowed. The list, which rows have been verified in a
browser and which have not, and where the keys may go, are on [Security and CSP](/security-and-csp).
If `font-src` does not allow the js host, the checkout paints in system fonts and the payment still
completes.
