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

# Using payment methods from the SDKs

> Which package to reach for, and the exact call that charges a card, a wallet or an APM.

# Using payment methods from the SDKs

Four packages can charge a payment. They differ in where they run and how much they do for you.

| Package                                                                 | Runs in | Reach for it when                                                                              |
| ----------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------- |
| [`@tagadapay/headless-sdk`](/developer-tools/headless-sdk/introduction) | Browser | You are building a custom storefront and want one call that handles 3DS, redirects and polling |
| [`@tagadapay/core-js`](/developer-tools/payments/core-js-payments)      | Browser | You need the low-level primitives — tokenization, wallet sheets, 3DS                           |
| [`@tagadapay/plugin-sdk`](/developer-tools/sdk/introduction)            | Browser | You are building a storefront plugin on TagadaPay hosting                                      |
| [`@tagadapay/node-sdk`](/developer-tools/node-sdk/quick-start)          | Server  | You are charging server-to-server, or orchestrating a backend flow                             |

<Tip>
  If you are unsure, start with `headless-sdk`'s `processPayment()`. It is the one function that
  covers cards, wallets and APMs, and it handles the parts people get wrong.
</Tip>

## The one call that handles everything

`processPayment()` charges, detects `requireAction`, runs the 3DS challenge, follows APM redirects
and polls until the payment reaches a terminal status.

```ts theme={null}
import { createHeadlessClient } from '@tagadapay/headless-sdk';

const tagada = createHeadlessClient({ storeId: 'store_xxx' });

const result = await tagada.payment.processPayment({
  checkoutSessionId: 'cs_xxx',
  paymentInstrumentId: 'pi_xxx',
});

if (result.status === 'succeeded') fulfil();
```

Everything below is the same flow taken apart, for when you need control over a step.

## Discovering what you can offer

Always render your payment UI from the store's configuration, not from a hard-coded list.

<CodeGroup>
  ```ts headless-sdk theme={null}
  const setup = await tagada.payment.getPaymentSetup('cs_xxx');
  const methods = await tagada.payment.getEnabledMethods('cs_xxx');
  const express = await tagada.payment.getExpressMethods('cs_xxx');
  ```

  ```ts core-js theme={null}
  import { getStorePaymentSetup } from '@tagadapay/core-js';

  const setup = await getStorePaymentSetup({
    storeId: 'store_xxx',
    apiKey: 'tp_pk_live_***',
  });
  ```

  ```ts node-sdk theme={null}
  const setup = await tagada.paymentSetup.get('store_xxx');
  ```
</CodeGroup>

Group the result by `type` — `card`, `wallet`, `apm` — to build your UI sections. See
[the config shape](/developer-tools/payments/alternative-payment-methods#the-config-shape).

## Cards

<Steps>
  <Step title="Tokenize in the browser">
    Raw card data never reaches your server or ours unvaulted.

    ```ts theme={null}
    const { tagadaToken } = await tagada.payment.tokenizeCard({
      cardNumber: '4242424242424242',
      expiryDate: '12/2030',
      cvc: '123',
    });
    ```
  </Step>

  <Step title="Pay with the token">
    `processPayment` creates the instrument from the token for you:

    ```ts theme={null}
    await tagada.payment.processPayment({
      checkoutSessionId: 'cs_xxx',
      tagadaToken,
    });
    ```

    To store the instrument first (e.g. to reuse it), call
    `const { paymentInstrument } = await tagada.payment.createInstrument({ tagadaToken })`
    and pass `paymentInstrumentId: paymentInstrument.id` instead.
  </Step>
</Steps>

Server-side, the equivalent is
`tagada.payments.process({ amount, currency, storeId, paymentInstrumentId })` — the Node SDK
charges vaulted instruments directly and takes no checkout session.

## Wallets

<CodeGroup>
  ```ts headless-sdk theme={null}
  // You open the sheet (core-js or your own ApplePaySession); headless-sdk
  // tokenizes the authorized wallet payload and charges the session.
  // Inside session.onpaymentauthorized:
  await tagada.payment.processApplePay({
    checkoutSessionId: 'cs_xxx',
    applePayToken: event.payment.token,
  });

  // Google Pay — inside the paymentsClient callback:
  await tagada.payment.processGooglePay({
    checkoutSessionId: 'cs_xxx',
    googlePayToken: paymentData.paymentMethodData.tokenizationData.token,
  });
  ```

  ```ts core-js theme={null}
  import { isApplePayAvailable, startApplePaySession } from '@tagadapay/core-js';

  if (await isApplePayAvailable()) {
    button.addEventListener('click', () => {
      startApplePaySession(config, request, {
        onSuccess: async (token) => { /* charge server-side */ },
        onError: (msg) => console.error(msg),
      });
    });
  }
  ```
</CodeGroup>

<Warning>
  The wallet sheet must be opened from a real user gesture. Do not `await` anything between the
  click and `startApplePaySession` — resolve your configuration beforehand. Full detail in
  [Apple Pay & Google Pay](/developer-tools/payments/wallets).
</Warning>

## Alternative payment methods

APMs need an explicit `paymentMethod` and a `processorId`, and they always come back with a
redirect rather than a final status.

<CodeGroup>
  ```ts headless-sdk theme={null}
  const result = await tagada.payment.processApm({
    checkoutSessionId: 'cs_xxx',
    paymentMethod: 'ideal',
    processorId: 'proc_xxx',
  });

  // finalize() resolves the action: it redirects the browser for APMs,
  // runs 3DS challenges, and polls to a terminal status otherwise.
  const outcome = await tagada.payment.finalize(result);
  if (outcome.status === 'succeeded') fulfil();
  ```

  ```ts node-sdk theme={null}
  const { payment } = await tagada.payments.process({
    amount: 4999,
    currency: 'EUR',
    storeId: 'store_xxx',
    customerId: 'cus_xxx',
    paymentMethod: 'klarna',
    processorId: 'proc_xxx',
    returnUrl: 'https://store.example/checkout/return',
  });
  ```
</CodeGroup>

### Coming back from the redirect

When the shopper returns to your `returnUrl`, resume the payment rather than assuming it worked:

```ts theme={null}
const resumed = await tagada.payment.maybeResumeFromUrl();
if (resumed?.status === 'succeeded') fulfil();
```

<Warning>
  The redirect return is not proof of payment. Fulfil on the
  [webhook](/developer-tools/node-sdk/webhooks-events), which is the authoritative result.
</Warning>

## Server-side payment operations

```ts theme={null}
import { Tagada } from '@tagadapay/node-sdk';

const tagada = new Tagada({ apiKey: process.env.TAGADA_API_KEY });

await tagada.payments.process({ amount, currency, storeId, paymentInstrumentId });
await tagada.payments.retrieve('pay_xxx');
await tagada.payments.refund({ paymentIds: ['pay_xxx'], amount: 1999 });
await tagada.payments.void({ paymentId: 'pay_xxx' });
await tagada.payments.continue('pay_xxx');
await tagada.payments.currencies();
await tagada.payments.processors();
```

<Note>
  `payments.refund()` and `payments.void()` are subject to what the underlying processor supports —
  CCAvenue, notably, cannot refund through us at all. Check the
  [capability matrix](/developer-tools/payments/processors#capability-matrix) before you rely on one.
</Note>

## Choosing a package

<AccordionGroup>
  <Accordion title="I'm building a custom storefront" icon="store">
    `headless-sdk`. Use `processPayment()` for cards and wallets, `processApm()` for redirects, and
    `getEnabledMethods()` to decide what to render.
  </Accordion>

  <Accordion title="I only need to tokenize" icon="lock">
    `core-js`. It is the smallest surface — `Tokenizer`, the wallet session helpers and 3DS, with no
    checkout opinions attached.
  </Accordion>

  <Accordion title="I'm charging from a backend" icon="server">
    `node-sdk`. Never put a secret key in a browser — use a restricted publishable key
    (`tp_pk_*`) client-side and keep `tp_sk_*` on the server.
  </Accordion>

  <Accordion title="I'm building a plugin on TagadaPay hosting" icon="puzzle-piece">
    `plugin-sdk`. It has the richest React surface — `usePayment`, wallet hooks and the full
    payment-action handler.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={3}>
  <Card title="Support matrix" icon="table" href="/developer-tools/payments/support-matrix">
    What each processor can charge.
  </Card>

  <Card title="Headless SDK" icon="cube" href="/developer-tools/headless-sdk/checkout-flow">
    The full checkout flow.
  </Card>

  <Card title="Node SDK" icon="server" href="/developer-tools/node-sdk/quick-start">
    Server-side quick start.
  </Card>
</CardGroup>
