App billing
What a shop pays your app: plans, one time charges and use.
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 or null | |
data.usage | AppUsage or null | Only on a plan that charges by use. |
data.scheduled | AppSubscription or null | A cheaper plan the merchant approved, to start when this period ends. |
data.pending | object | |
data.pending.subscriptions | array of AppSubscription | |
data.pending.purchases | array of AppPurchase | |
data.purchases | array of 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 |
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 |
curl -X POST "https://api.storeware.ai/api/v1/app-billing/subscriptions" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @body.jsonEnd 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 |
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 |
curl -X POST "https://api.storeware.ai/api/v1/app-billing/purchases" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @body.jsonReport 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 | The period’s usage after this record. |
curl -X POST "https://api.storeware.ai/api/v1/app-billing/usage" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @body.jsonCredit 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) |
curl -X POST "https://api.storeware.ai/api/v1/app-billing/credits" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @body.json