Skip to content

List a purchase’s apps

GET
/teams/{teamId}/bundle-purchases/{bundlePurchaseId}/apps
curl --request GET \
--url https://qinto-api.blotout.io/teams/7b8d1a52-6c1e-4b6f-9a30-2f8a54d1c3e9/bundle-purchases/9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f/apps \
--header 'Authorization: Bearer <token>'

Reads a bundle purchase with the apps it covers right now and the sites each one is installed on. Call it to choose what to install with the install operation, at no charge beyond the bundle.

How it works

The apps are those of the bundle’s developer that the purchase covers, with the version an install would take and whether that version runs without visitor consent. An app that joined the bundle after the purchase is listed like any other. An ended purchase lists no app. Only a token with a user reads; a team API token is refused.

Required permissions

  • team:read on the team
teamId
required

Unique id (UUID) of the team that owns the addressed resources, as shown in the team settings on the Blotout platform.

string format: uuid

Example

7b8d1a52-6c1e-4b6f-9a30-2f8a54d1c3e9

Unique id (UUID) of the team that owns the addressed resources, as shown in the team settings on the Blotout platform.

bundlePurchaseId
required

Unique id (UUID) of the purchase, as the list operation returns it.

string format: uuid

Example

9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f

Unique id (UUID) of the purchase, as the list operation returns it.

The purchase and its apps.

Media typeapplication/json
object
purchase
required

A team’s holding of one bundle, with the terms copied when it bought it and the sites it chose.

object
bundlePurchaseId
required

Id of the purchase.

string
teamId
required

The team that holds it.

string
bundleId
required

The bundle bought.

string
bundleName
required

The bundle’s current name.

string
publisher
required

The developer organization’s name.

string
linkId
required

The bundle link the purchase came through; null from the app store.

string | null
pricingModel
required

The pricing model copied at purchase.

string
Allowed values: fixed fixed_usage usage free
basePriceCents
required

The price per interval copied at purchase, in US cents.

integer | null
billingInterval
required

How often the price is charged.

string | null
Allowed values: monthly yearly one_time
trialDays
required

The free days copied at purchase; null or 0 for none.

integer | null
siteLimit
required
Any of:
integer
extraSitePriceCents
required

The price per interval of each site past the limit; null when none are sold.

integer | null
services
required

The services copied at purchase.

Array<object>

A service the developer delivers, which the bundle price covers.

object
name
required

Name of the service. Empty only on a bundle that isn’t published yet.

string
detail
required

What the team gets. Empty when not set.

string
priceCents
required

What the service costs on its own, in US cents. Null only on a bundle that isn’t published yet.

integer | null
basis
required

How the price on its own is billed.

string
Allowed values: monthly one_time
usageCapCents
required

The most usage adds to the bill each month, in US cents.

integer | null
meterTerms
required

The priced meters copied at purchase.

Array<object>

What one meter of one app costs on a bundle. A meter with no term is free.

object
appId
required

Id of the app that reports the meter.

string
key
required

Key of the meter in that app. The same key in two apps is two terms.

string
name
required

Name of the meter on the bundle.

string
unit
required

Plural unit, as the bill shows it. Empty only on a bundle that isn’t published yet.

string
includedAmount
required

Units included each month for the whole team, across its sites.

number
priceMicros
required

Price past the included amount, in US micro-dollars.

integer
perUnits
required

How many units that price covers. Null only on a bundle that isn’t published yet.

integer | null
appMode
required

The app mode copied at purchase.

string
Allowed values: selected all exclude
appIds
required

The bundle’s stored app list copied at purchase; empty for All apps.

Array<string>
sites
required

The sites the purchase covers, A–Z by hostname.

Array<object>
object
domainId
required

Id of the site.

string
domain
required

The site’s hostname.

string
termsAcceptedByUserId
required

Who accepted the apps’ terms.

string | null
termsAcceptedAt
required

When the terms were accepted.

string format: date-time
chargeApprovedByUserId
required

Who approved the charge; null for a free bundle.

string | null
chargeApprovedAt
required

When the charge was approved; null for a free bundle.

string | null format: date-time
startedAt
required

The purchase instant. Charges start the next UTC day.

string format: date-time
endedAt
required

When the purchase ends: the first instant it no longer covers, still ahead while a cancel waits to take effect; null while active.

string | null format: date-time
apps
required

The apps the purchase covers right now, A–Z by name; empty once it ended.

Array<object>

One app a bundle purchase covers, and where it is installed.

object
appId
required

Id of the app.

string
slug
required

Slug of the app, to pass to the install operation.

string
name
required

Display name of the app.

string
iconHash
required

Content hash of the app’s icon; null when it has none.

string | null
version
required

The version an install takes: the newest the sites may run.

string
necessary
required

Whether that version runs without visitor consent, so its slug must be in acknowledgeNecessary.

boolean
legal
required

The developer’s legal documents, accepted when the bundle was bought.

object
termsUrl
required

The developer’s terms for the app.

string
privacyUrl
required

The developer’s privacy policy for the app.

string
installedOn
required

Ids of the purchase’s sites that already run the app.

Array<string>

Example

{
"purchase": {
"bundlePurchaseId": "9c1d2e3f-4a5b-4c6d-8e7f-0a1b2c3d4e5f",
"teamId": "7b8d1a52-6c1e-4b6f-9a30-2f8a54d1c3e9",
"bundleId": "2b7e4d10-8a3c-4f56-9e21-7c0d5b8f3a64",
"bundleName": "Growth Stack",
"publisher": "Acme Dev",
"linkId": null,
"pricingModel": "fixed",
"basePriceCents": 2900,
"billingInterval": "monthly",
"trialDays": 14,
"siteLimit": 3,
"extraSitePriceCents": 500,
"services": [
{
"name": "Priority support",
"detail": "4-hour response, shared Slack channel",
"priceCents": 20000,
"basis": "monthly"
}
],
"usageCapCents": 10000,
"meterTerms": [
{
"appId": "7f3a1c92-4b6d-4e8a-b1d3-5c9e2f7a6b10",
"key": "events",
"name": "Events",
"unit": "events",
"includedAmount": 100000,
"priceMicros": 500000,
"perUnits": 1000
}
],
"appMode": "selected",
"appIds": [],
"sites": [
{
"domainId": "3f2a9c81-5d47-4e0b-8c66-91b2a7f04d15",
"domain": "q.shop.example.com"
}
],
"termsAcceptedByUserId": "1f2e3d4c-5b6a-4978-8f0e-9d8c7b6a5f4e",
"termsAcceptedAt": "2026-11-08T12:00:00.000Z",
"chargeApprovedByUserId": null,
"chargeApprovedAt": "2026-11-08T12:00:00.000Z",
"startedAt": "2026-11-08T12:00:00.000Z",
"endedAt": "2026-11-08T12:00:00.000Z"
},
"apps": [
{
"appId": "5a6b7c8d-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
"slug": "facebook-capi",
"name": "Facebook CAPI",
"iconHash": null,
"version": "1.4.1",
"necessary": false,
"legal": {
"termsUrl": "https://example.com/legal/terms",
"privacyUrl": "https://example.com/legal/privacy"
},
"installedOn": [
"3f2a9c81-5d47-4e0b-8c66-91b2a7f04d15"
]
}
]
}

invalid_params — A path parameter failed validation (for example a malformed UUID); details pinpoints the offending parameter.

Media typeapplication/json
object
error
required

Machine-readable error slug; switch on this value rather than on the HTTP status alone.

string
Allowed values: invalid_params
details

Field-level validation errors: a tree keyed by input property, each node carrying an errors array of human-readable messages. Render it to help the caller correct the request.

object
key
additional properties

Example

{
"error": "invalid_params",
"details": {
"errors": [],
"properties": {
"teamId": {
"errors": [
"Invalid UUID"
]
}
}
}
}

unauthenticated — The Authorization: Bearer token is missing, malformed, or no longer valid. Generate a team API token or obtain a new OAuth access token.

Media typeapplication/json
object
error
required

Machine-readable error slug; switch on this value rather than on the HTTP status alone.

string
Allowed values: unauthenticated

Example

{
"error": "unauthenticated"
}

forbidden — The bearer credential lacks the required permission or belongs to another team, or its user lacks the organization role a developer operation needs. Update its policies, use a credential bound to the addressed team, or ask an organization owner for the role; message states the reason when one is known.

Media typeapplication/json
object
error
required

Machine-readable error slug; switch on this value rather than on the HTTP status alone.

string
Allowed values: forbidden
message

Human-readable reason for this specific failure, intended for display — do not parse it programmatically.

string

Example

{
"error": "forbidden",
"message": "The Cloudflare API token is invalid or expired."
}

not_found — The addressed resource does not exist within this team; check the id and retry.

Media typeapplication/json
object
error
required

Machine-readable error slug; switch on this value rather than on the HTTP status alone.

string
Allowed values: not_found

Example

{
"error": "not_found"
}

internal — Unexpected server error. Nothing is guaranteed to have been persisted; idempotent operations are safe to retry.

Media typeapplication/json
object
error
required

Machine-readable error slug; switch on this value rather than on the HTTP status alone.

string
Allowed values: internal

Example

{
"error": "internal"
}