> ## Documentation Index
> Fetch the complete documentation index at: https://docs.slash.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Accept your first card payment with the Slash API.

Slash payment processing lets you accept card payments on your own site. You
create a payment intent server-side with your API key, collect the payment in
the browser with [Payment Elements](/docs/payments/payment-elements), and
fulfill once the intent settles.

<Info>
  Slash Payment Processing is in beta and not enabled for all accounts. Contact
  [support@joinslash.com](mailto:support@joinslash.com) to get access.
</Info>

## 1. Create a payment intent

Call [`POST /payments/payment-intent`](/api-reference/payment-intent-post)
with a legal-entity-scoped API key. Pass a
[supported `currency`](/api-reference/payment-intent-post), with `amount` in
that currency's smallest unit. Include an `X-Idempotency-Key` so a retried
request never creates a duplicate — see
[Idempotent requests](/docs/payments/idempotent-requests).

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.slash.com/payments/payment-intent \
    -X POST \
    -H "X-API-Key: $SLASH_API_KEY" \
    -H "X-Idempotency-Key: order_1234" \
    -H "Content-Type: application/json" \
    -d '{ "amount": 5000, "currency": "usd", "metadata": { "orderId": "ord_1234" } }'
  ```

  ```ts Node.js theme={null}
  const res = await fetch("https://api.slash.com/payments/payment-intent", {
    method: "POST",
    headers: {
      "X-API-Key": process.env.SLASH_API_KEY,
      "X-Idempotency-Key": "order_1234",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      amount: 5000,
      currency: "usd",
      metadata: { orderId: "ord_1234" },
    }),
  });
  const { paymentIntent, clientSecret } = await res.json();
  ```
</CodeGroup>

The response includes the payment intent and a `clientSecret`:

```json theme={null}
{
  "paymentIntent": {
    "id": "acq_payment_intent_...",
    "status": "pending",
    "amount": 5000,
    "currency": "usd",
    "metadata": { "orderId": "ord_1234" },
    "createdAt": "2026-09-10T00:00:00.000Z",
    "updatedAt": "2026-09-10T00:00:00.000Z"
  },
  "clientSecret": "..."
}
```

The `clientSecret` is the browser's credential for this one intent: it
authorizes loading the payment form *and* confirming the payment, which is
what moves the intent from `pending` to `processing`. It grants nothing else.
Return it to your frontend, but never log it or store it in browser
persistence.

## 2. Collect the payment

In the browser, wrap your checkout in `<PaymentProvider>` from
[`@slashfi/elements-react`](/docs/payments/payment-elements) with the
`clientSecret`, render `<PaymentElement />` where the card form should go, and
call `confirm()` with the buyer's email, name, and billing address when they
press pay.

```tsx theme={null}
import {
  BrandingElement,
  PaymentElement,
  PaymentProvider,
  usePaymentElements,
} from '@slashfi/elements-react';

function PayButton({ email, name, billingAddress }) {
  const payment = usePaymentElements();

  return (
    <button
      disabled={payment.state !== 'ready' || !payment.canConfirm}
      onClick={async () => {
        const result = await payment.confirm?.({ email, name, billingAddress });
        if (result.type === 'error') return showError(result.error.message);
        // Buyer is done; fulfillment happens server-side in step 3.
        goToPendingPage(result.paymentIntentId);
      }}
    >
      Pay
    </button>
  );
}

export function Checkout({ clientSecret }) {
  return (
    <PaymentProvider clientSecret={clientSecret}>
      <PaymentElement />
      <PayButton {...buyerDetails} />
      <BrandingElement />
    </PaymentProvider>
  );
}
```

A `processing` result means the buyer finished, not that the payment settled.
See the [Payment Elements](/docs/payments/payment-elements) reference for the
full component, hook, and error surface.

## 3. Fulfill the order

Fulfill when the payment intent's `status` becomes `succeeded`. Subscribe to
the
[`payments.payment_intent.updated`](/docs/payments/webhooks/payment-intent-updated)
webhook and read the intent back with
[`GET /payments/payment-intent/{id}`](/api-reference/payment-intent-get-by-id)
when it fires; if you cannot receive webhooks, poll that endpoint instead.
Your `metadata` is returned on every read, so you can correlate the intent to your order without extra
lookups.

A browser-side success signal can be forged — never grant goods or services
on it alone.
