# App billing

> What a shop pays your app: plans, one time charges and use.

Source: https://storeware.ai/docs/api-reference/rest/app-billing

## Get your app’s billing on this shop

`GET /api/v1/app-billing`

The plan in force, this period’s usage, a cheaper plan waiting to start, the charges waiting for the merchant, the one-time charges approved among your last 50, and the plans your installed release declares, priced in the shop’s currency.

Answers only your app’s own token for the shop, and needs no permission.

**Answers** `200`

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.currency` | string | The shop’s billing currency. Every amount here is in its minor unit: cents, pence, paise. One of `usd`, `gbp`, `eur`, `inr`. |
| `data.subscription` | [AppSubscription](https://storeware.ai/docs/api-reference/rest/objects#appsubscription) or null |  |
| `data.usage` | [AppUsage](https://storeware.ai/docs/api-reference/rest/objects#appusage) or null | Only on a plan that charges by use. |
| `data.scheduled` | [AppSubscription](https://storeware.ai/docs/api-reference/rest/objects#appsubscription) or null | A cheaper plan the merchant approved, to start when this period ends. |
| `data.pending` | object |  |
| `data.pending.subscriptions` | array of [AppSubscription](https://storeware.ai/docs/api-reference/rest/objects#appsubscription) |  |
| `data.pending.purchases` | array of [AppPurchase](https://storeware.ai/docs/api-reference/rest/objects#apppurchase) |  |
| `data.purchases` | array of [AppPurchase](https://storeware.ai/docs/api-reference/rest/objects#apppurchase) | One-time charges approved, newest first. |
| `data.plans` | array of object |  |
| `data.plans[].key` | string |  |
| `data.plans[].name` | string |  |
| `data.plans[].description` | string or null |  |
| `data.plans[].interval` | string | One of `month`, `year`. |
| `data.plans[].amountMinor` | integer | Each period’s price in the shop’s currency. |
| `data.plans[].currency` | string | The shop’s billing currency. Every amount here is in its minor unit: cents, pence, paise. One of `usd`, `gbp`, `eur`, `inr`. |
| `data.plans[].trialDays` | integer |  |
| `data.plans[].features` | array of string |  |
| `data.plans[].releaseId` | string (uuid) or null | The release that declares it. |
| `data.plans[].usageCapMinor` | integer or null |  |
| `data.plans[].usageTerms` | string or null |  |

```bash
curl "https://api.storeware.ai/api/v1/app-billing" \
  -H "Authorization: Bearer $TOKEN"
```

## Ask the merchant to approve a plan

`POST /api/v1/app-billing/subscriptions`

Asks for one of the plans your installed release declares. Send the merchant to `confirmationUrl`: nothing is charged until they approve, and they have 48 hours to. `returnUrl` must be https on your app’s own address (its `app.url`, webhook URL or a redirect URI). Asking for the plan already in force answers with it and changes nothing. At most 5 charges may wait for an answer at once. Send the same `idempotencyKey` again and you are answered with the first result, so a retry never charges twice.

Answers only your app’s own token for the shop, and needs no permission.

**Body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `plan` | string | Yes | 1 to 32 characters. |
| `returnUrl` | string (uri) | Yes | Up to 2,000 characters. |
| `test` | boolean | No |  |
| `idempotencyKey` | string | No | 1 to 200 characters. |

**Answers** `201`

| Field | Type | Description |
| --- | --- | --- |
| `data` | [AppSubscription](https://storeware.ai/docs/api-reference/rest/objects#appsubscription) |  |

```bash
curl -X POST "https://api.storeware.ai/api/v1/app-billing/subscriptions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @body.json
```

## End your plan on this shop

`POST /api/v1/app-billing/subscriptions/{subscriptionId}/cancel`

Ends the plan when the period the merchant has paid for ends. Until then it stays in force.

Answers only your app’s own token for the shop, and needs no permission.

**Parameters**

| Parameter | In | Type | Description |
| --- | --- | --- | --- |
| `subscriptionId` | path | string | The subscription. |

**Answers** `200`

| Field | Type | Description |
| --- | --- | --- |
| `data` | [AppSubscription](https://storeware.ai/docs/api-reference/rest/objects#appsubscription) |  |

```bash
curl -X POST "https://api.storeware.ai/api/v1/app-billing/subscriptions/$SUBSCRIPTION_ID/cancel" \
  -H "Authorization: Bearer $TOKEN"
```

## Ask the merchant to approve a one-time charge

`POST /api/v1/app-billing/purchases`

Give a price in every currency: the shop is charged in its own, and nothing is converted. Send the merchant to `confirmationUrl`; nothing is charged until they approve, and they have 48 hours to. `returnUrl` follows the same rule as for a plan. Send the same `idempotencyKey` again and you are answered with the first result, so a retry never charges twice.

Answers only your app’s own token for the shop, and needs no permission.

**Body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | 1 to 120 characters. |
| `prices` | object | Yes |  |
| `prices.usd` | integer | Yes | From 1 to 10,000,000. |
| `prices.gbp` | integer | Yes | From 1 to 10,000,000. |
| `prices.eur` | integer | Yes | From 1 to 10,000,000. |
| `prices.inr` | integer | Yes | From 1 to 10,000,000. |
| `returnUrl` | string (uri) | Yes | Up to 2,000 characters. |
| `test` | boolean | No |  |
| `idempotencyKey` | string | No | 1 to 200 characters. |

**Answers** `201`

| Field | Type | Description |
| --- | --- | --- |
| `data` | [AppPurchase](https://storeware.ai/docs/api-reference/rest/objects#apppurchase) |  |

```bash
curl -X POST "https://api.storeware.ai/api/v1/app-billing/purchases" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @body.json
```

## Report what the shop used

`POST /api/v1/app-billing/usage`

Adds to this period’s usage, in the plan’s currency, on a plan that charges by use. It is billed when the period ends. Past the period’s cap it is refused with 402 `app_usage_cap_reached`, and on a plan with no usage with 409. Send the same `idempotencyKey` again and you are answered with the first result, so a retry never charges twice.

Answers only your app’s own token for the shop, and needs no permission.

**Body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `amountMinor` | integer | Yes | From 1 to 10,000,000. |
| `description` | string | Yes | 1 to 200 characters. |
| `idempotencyKey` | string | No | 1 to 200 characters. |

**Answers** `201`

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.id` | string (uuid) |  |
| `data.amountMinor` | integer |  |
| `data.currency` | string |  |
| `data.description` | string |  |
| `data.createdAt` | string (date-time) |  |
| `data.usage` | [AppUsage](https://storeware.ai/docs/api-reference/rest/objects#appusage) | The period’s usage after this record. |

```bash
curl -X POST "https://api.storeware.ai/api/v1/app-billing/usage" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @body.json
```

## Credit the shop

`POST /api/v1/app-billing/credits`

Takes an amount off the shop’s next statement, in its billing currency. A credit can come to no more than the shop paid your app in the last year, less what it has already been credited; past that it is refused with 409. Send the same `idempotencyKey` again and you are answered with the first result, so a retry never charges twice.

Answers only your app’s own token for the shop, and needs no permission.

**Body**

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `amountMinor` | integer | Yes | From 1 to 10,000,000. |
| `description` | string | Yes | 1 to 200 characters. |
| `idempotencyKey` | string | No | 1 to 200 characters. |

**Answers** `201`

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.id` | string (uuid) |  |
| `data.amountMinor` | integer |  |
| `data.currency` | string |  |
| `data.description` | string |  |
| `data.test` | boolean | True when no money moves. |
| `data.createdAt` | string (date-time) |  |

```bash
curl -X POST "https://api.storeware.ai/api/v1/app-billing/credits" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @body.json
```
