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

# Payments

> Charge merchants from your app, once or on a schedule. Salesive keeps 5% and credits the rest to your payout store's wallet.

Your app can charge the merchant it is installed for. You ask, the store owner approves in
the Salesive dashboard, and the money moves from their wallet (or card) to your payout store.
Salesive keeps **5%** of every payment. You never touch card details and you never move money
yourself.

## How it works

**1. Create a charge or a subscription**

Call the [Billing API](https://docs.salesive.com/apps-api/endpoint/billing/create-charge.md) with your app token.
Nothing is charged yet. The response has a `confirmationUrl`.

**2. Send the merchant to confirmationUrl**

Redirect them there. The store owner sees
your app, the price and the terms, and approves or declines. Only the owner can approve.

**3. Learn the result**

Listen for the `charges/paid` or `subscriptions/activated` [webhook](#webhooks), or read the
charge. If you set a `returnUrl`, the merchant is sent back to it.

**4. Get paid**

The payout store's wallet is credited the moment the payment succeeds: the price minus 5%,
converted to that wallet's currency.

## Before you can charge

1. Pick a **payout store** in the Developer console (**Apps > Developer > your app > Billing**).
   It must be a store you own. This is where your earnings go.
2. Request the scopes you need: `WRITE_CHARGES` to create and cancel, `READ_CHARGES` to read
   and to receive billing webhooks.
3. Your app must be live (approved and published). Charging is switched on per payout store by
   Salesive: until it is, creating a charge returns `403` with code `BILLING_NOT_ENABLED`. Contact
   us to enable it.
4. An app cannot charge the store that receives its earnings, so test on a separate store.

## Pricing and fees

| | |
| - | - |
| Currencies | `USD` or `NGN`. You choose per charge. |
| Limits | USD 1 to 1,000. NGN 500 to 1,500,000. |
| Platform fee | 5% of the price, taken from your side. A $10.00 charge pays you $9.50. |
| Merchant pays | The price converted to the currency of the wallet they pick, at the exchange rate when they pay. Rounded up to the cent. |
| You receive | The price minus 5%, converted to your payout wallet's currency, rounded to the cent. |

The fee and your net amount are fixed when the charge is created and returned as `platformFee` and
`netAmount`. They never change afterwards.

## One-time charges

```bash theme={null}
curl -X POST https://api.salesive.com/api/v1/app-billing/charges \
  -H "Authorization: Bearer app_<token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Extra seats",
    "description": "5 additional seats",
    "amount": 15,
    "currency": "USD",
    "returnUrl": "https://myapp.example.com/billing/done",
    "idempotencyKey": "order-A-1042"
  }'
```

The merchant can pay from any wallet with enough balance, or by card. A request that is not
approved within **48 hours** expires. Send an `idempotencyKey` so a retried request returns the
charge you already made instead of creating a second one.

`returnUrl` must be on your app URL's origin or one of your redirect URIs.

## Subscriptions

```bash theme={null}
curl -X POST https://api.salesive.com/api/v1/app-billing/subscriptions \
  -H "Authorization: Bearer app_<token>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Pro plan", "amount": 10, "currency": "USD", "interval": "month" }'
```

The merchant approves once and picks a wallet. The first period is taken straight away. After
that, **every renewal is taken automatically from that wallet**.

| Event | What happens |
| - | - |
| 3 days before a renewal | The merchant is emailed the date and amount. |
| Renewal day | The wallet is charged. You receive `subscriptions/renewed`. |
| Not enough balance | The subscription becomes `past_due` and is retried every day. You receive `subscriptions/past_due`. |
| 3 failed attempts in a row | The subscription is cancelled. You receive `subscriptions/cancelled`. |
| Merchant cancels | It stays active until the end of the period they paid for, then ends. |
| App uninstalled | Subscriptions end immediately and no further charges are made. |

Renewals stay on the same day of the month they started, shortened for short months (a
subscription started on the 31st renews on the 28th, 29th or 30th, then returns to the 31st).
Each renewal converts the price at that day's exchange rate, so the amount in the merchant's
wallet currency can differ slightly from the last one. Subscriptions are wallet only; the card
option is for one-time charges.

### Granting access

Do not decide access from webhooks alone. Read the subscription and keep the merchant's access
on while:

* `status` is `active` or `past_due`, and
* `currentPeriodEnd` is in the future.

A `cancelAtPeriodEnd` subscription is still `active` until its period ends.

### Cancelling and managing

Merchants manage their subscriptions under **Apps > Billing** in the dashboard. They can cancel,
resume one that is scheduled to end, and change the wallet it is paid from. Your app can cancel
too with [Cancel a subscription](https://docs.salesive.com/apps-api/endpoint/billing/cancel-subscription.md). It ends at the
end of the paid period unless you pass `immediately: true`.

## Webhooks

Billing events arrive on your normal [webhook URL](https://docs.salesive.com/apps-api/webhooks.md), signed the same way. You
receive them only for installations that granted `READ_CHARGES`, and only for your own charges.

| Topic | When |
| - | - |
| `charges/paid` | A charge was paid. This includes each subscription payment. |
| `charges/declined` | The merchant declined it. |
| `charges/expired` | It was not approved in time. |
| `subscriptions/activated` | The merchant approved and the first payment went through. |
| `subscriptions/renewed` | A renewal was paid. |
| `subscriptions/past_due` | A renewal failed and will be retried. |
| `subscriptions/cancel_scheduled` | The subscription will end at the end of the paid period. |
| `subscriptions/cancelled` | It ended. Check `cancelledBy` and `cancelReason`. |
| `subscriptions/declined` | The merchant declined it. |
| `subscriptions/expired` | It was not approved in time. |

The payload carries ids only, like every other webhook. `resourceId` is the charge or
subscription, and `chargeId` is added when a subscription event came from a payment. Fetch the
record to read amounts and status.

## Test mode

On a **development install** (a store you install the app on from the Developer console in
Development mode), charges and subscriptions are marked `test: true`. The merchant approves
them with one click, no wallet is needed, and no money moves. Fees are not taken and nothing is
credited. Use this to build and test your whole flow. Test requests skip the live and payout
checks, so they work before your app is approved.

## Refunds and limits

* There is no refund endpoint. A paid charge is final. To refund a merchant, contact Salesive
  support with the charge reference.
* A suspended app, or a suspended store, pauses renewals. When it is reinstated the next renewal
  is taken, so a merchant may be charged once for the missed time.
* There are no free trials. Give a trial in your own app, then create the subscription when it
  ends.
* Up to 50 requests per installation may wait for the merchant at once.

## Errors

| Status | Meaning |
| - | - |
| `400` | Invalid body, amount out of range, unsupported currency, or a `returnUrl` on a different origin. |
| `403` | Missing scope, the app is not live, no payout store (`NO_PAYOUT_STORE`), or charging is not enabled (`BILLING_NOT_ENABLED`). |
| `404` | The charge or subscription does not exist for this installation. |
| `429` | Too many unanswered requests for this merchant. |

## Next steps

* [Create a charge](https://docs.salesive.com/apps-api/endpoint/billing/create-charge.md)
* [Create a subscription](https://docs.salesive.com/apps-api/endpoint/billing/create-subscription.md)
* [Webhooks](https://docs.salesive.com/apps-api/webhooks.md)
* [Scopes & permissions](https://docs.salesive.com/apps/scopes-permissions.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.