> ## 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.

# Choose how you accept payments

> Four ways to accept a payment with TagadaPay. This page picks the right one in under a minute.

# Choose how you accept payments

Four ways to accept a payment. They are not interchangeable. Combining two paths on the same customer-initiated payment (CIT — your customer is present) is the most common integration mistake.

```mermaid theme={null}
flowchart TD
  start[What are you building]
  start --> ownOrder[You already have the order]
  start --> tagadaCart[TagadaPay should manage cart and upsells]
  start --> hosted[You want a TagadaPay-hosted page]
  start --> later[Charge a saved card later]

  ownOrder --> coreJs[core-js plus payments.process]
  tagadaCart --> headless[Headless SDK]
  hosted --> plugin[Plugin SDK or funnel]
  later --> mit[Node payments.process]
```

| What you want                                                                                                        | Use                                                                                                                                                                         |
| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Accept a payment when you already have the order (Medusa, WooCommerce, a custom order API)                           | [`@tagadapay/core-js`](/developer-tools/payments/core-js-payments) in the browser + Node [`tagada.payments.process()`](/developer-tools/node-sdk/quick-start) on the server |
| Build a checkout where TagadaPay manages the cart, upsells, and funnel — on your domain                              | [`@tagadapay/headless-sdk`](/developer-tools/headless-sdk/introduction) (install `@tagadapay/core-js` as a peer for cards)                                                  |
| Use a TagadaPay-hosted checkout page                                                                                 | [`@tagadapay/plugin-sdk`](/developer-tools/sdk/introduction)                                                                                                                |
| Charge a saved card later — subscriptions, retries, metered billing (MIT — merchant-initiated, customer not present) | Node [`tagada.payments.process()`](/developer-tools/node-sdk/quick-start), regardless of which path created the instrument                                                  |

Working Headless example: [headless-vanilla](https://github.com/TagadaPay/examples/tree/main/headless-vanilla).

***

## Same name, different call

| Call                              | Where                 | What it does                                                    |
| --------------------------------- | --------------------- | --------------------------------------------------------------- |
| `tagada.payment.processPayment()` | Browser, Headless SDK | Pays a **checkout session**. Handles 3DS, redirects, polling.   |
| `tagada.payment.pay()`            | Browser, Headless SDK | Lower-level session pay. Prefer `processPayment()`.             |
| `tagada.payments.process()`       | Server, Node SDK      | Charges a **vaulted instrument**. No checkout session required. |

***

## What not to do

<AccordionGroup>
  <Accordion title="Do combine Headless with core-js as a peer">
    Headless dynamically imports `@tagadapay/core-js` for `tokenizeCard()`. Install both. That is the intended pairing, not two competing checkouts.
  </Accordion>

  <Accordion title="Do charge later with payments.process after any first payment">
    First payment (customer present) with Headless `processPayment()` **or** core-js + `/payments/process`. Later charges use Node `payments.process()` against the saved instrument. Same card, two different moments.
  </Accordion>

  <Accordion title="Do not create a Headless session and then charge with payments.process">
    A checkout session is not a payment. If you `createSession()` and then call `/payments/process` without paying that session, the cart is left unpaid, 3DS returns to the wrong page, and the hosted checkout link often points to a placeholder. Pick **one** path for the first payment.
  </Accordion>
</AccordionGroup>

***

## Headless `returnUrl` vs `checkoutUrl`

On a **self-hosted** Headless checkout:

* `returnUrl` is the page that hosts `usePayment` / `maybeResumeFromUrl`. After 3DS the bank sends the shopper back **there**.
* `checkoutUrl` is generated by TagadaPay. Headless **cannot set it**. Do not redirect the shopper to `session.checkoutUrl` when you are rendering checkout yourself.
* To hop from a cart page to your own checkout path, use `tagada.checkout.createSessionUrl()` — it builds a URL on **your** origin with `checkoutToken` + `sessionToken`.

`checkoutUrl` is for TagadaPay-hosted checkouts only.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Accept a payment with your own cart" icon="credit-card" href="/developer-tools/payments/core-js-payments">
    Tokenize in the browser, charge with payments.process
  </Card>

  <Card title="Headless SDK" icon="plug" href="/developer-tools/headless-sdk/introduction">
    Custom UI, TagadaPay manages the cart
  </Card>

  <Card title="Plugin SDK" icon="puzzle-piece" href="/developer-tools/sdk/introduction">
    Pages hosted on TagadaPay
  </Card>

  <Card title="Node SDK" icon="node-js" href="/developer-tools/node-sdk/quick-start">
    Server charges, including later rebills
  </Card>
</CardGroup>
