Plans and purchases

See the plans Wingspan offers an Account, check eligibility, and buy a plan with a signed consent using the V3 API.

A Plan is something an Account can buy from Wingspan. A Purchase is the act of buying one. Creating a Purchase also creates the Subscription that carries the Plan, in one step. See Subscriptions for what happens next.

Prerequisites

  • revenue.catalog:read to read Plans and revenue.purchases:read or revenue.purchases:write for Purchases.
  • A signed-in Person session to create a Purchase. The Purchase records who signed the terms, so an API key or service account is refused.
  • X-Wingspan-Account set to the Account that buys.

Endpoints

PurposeMethod and path
List PlansGET /v3/platform/plans
Get a PlanGET /v3/platform/plans/{planId}
Create a PurchasePOST /v3/platform/purchases
List PurchasesGET /v3/platform/purchases
Get a PurchaseGET /v3/platform/purchases/{purchaseId}
Cancel a PurchasePOST /v3/platform/purchases/{purchaseId}/cancel
Renew a PurchasePOST /v3/platform/purchases/{purchaseId}/renew
List catalog itemsGET /v3/platform/purchase-catalog
Get a catalog itemGET /v3/platform/purchase-catalog/{skuId}

Find a Plan the Account can buy

Plans are personalized. Each one reports isEligible and, when it is false, a list of blockers.

ParameterValues
filter[type][eq]Service, Benefit
filter[isEligible][eq]true, false
filter[acquisition.mode][eq]Direct, DomainService
sortname, status, type or isEligible, each asc or desc
expandproducts adds the Plan's products. Without it they are left out of the list.
curl -g "https://api.wingspan.app/v3/platform/plans?filter[isEligible][eq]=true&filter[type][eq]=Service&expand=products" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "X-Wingspan-Account: Nw7kQ2pLx9RtVb3mHc5dZa"

A Plan has id, name, description, type, status (Active or ClosedToNewBusiness), prices, termOptions, requiredConsents, acquisition, isEligible and blockers. Each price has skuId, currency, unit (Quantity or Percentage), amount or rateBp, validFrom, and termOptionId. A term option has an id and an interval of Monthly, Annual, or MultiYear with a value.

Blocker code is one of PlanNotPurchasable, PlanClosedToNewBusiness, RequirementNotFulfilled, ConcurrentSubscriptionNotAllowed or EnrollmentWindowClosed. RequirementNotFulfilled also carries a requirementId. See Requirements and eligibility.

acquisition.mode tells you where the Plan is bought. A DomainService Plan is bought through its own service flow, and acquisition.platformPurchaseSupported says whether you can buy it here.

Create a Purchase

Send Idempotency-Key. It is required.

FieldRequiredNotes
planIdYesA Plan the Account is eligible for.
consentsYesOne entry for each item in the Plan's requiredConsents: termsRef, version, documentSha256, signedAt, and optional consentProvenance.
termOptionIdNoOne of the Plan's termOptions.
instrumentSelection.fundingInstrumentIdNoThe funding instrument to bill.
fulfillmentDataNoData the Plan's fulfillment needs.

You cannot send a price. Wingspan reads it from the Plan. The request does not take a payment.

curl -X POST https://api.wingspan.app/v3/platform/purchases \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "X-Wingspan-Account: Nw7kQ2pLx9RtVb3mHc5dZa" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "planId": "Zc6vKm2PxQ8tNb4wRd7LhE",
    "termOptionId": "Tm3yWq9HcB5xKd2nVp8JaF",
    "consents": [
      {
        "termsRef": "terms/service-agreement",
        "version": "2026-01",
        "documentSha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
        "signedAt": "2026-11-02T16:00:00Z"
      }
    ]
  }'

The values are illustrative. Copy termsRef, version and documentSha256 from the Plan's requiredConsents.

The response is 201 with the Purchase: id, planId, planVersion, status (Pending, Completed, Failed), subscriptionId, pricing, consents, subscription (id, status, activationGates) and events. pricing has currency, lineItems, total, grossTotal, taxTotal and taxDeterminationPending. While the Subscription is still being provisioned, the body adds provisioningPending: true. Read the Purchase again later.

The Idempotent-Replayed header says whether the response is a replay. Replaying a key returns 201 with the original response, or 200 with the current Purchase when the original is older.

Errors

StatusCause
400Idempotency-Key is missing.
401The Person session is not valid.
403You called with an API key or service account. Consent needs a Person session.
409The Plan cannot be bought now. The problem lists any eligibility blockers, such as ConcurrentSubscriptionNotAllowed.
422A field is invalid. The problem lists errors by field.
503The purchase service did not return a valid result. Retry later with the same Idempotency-Key.

Cancel and renew

Cancel a Purchase and Renew a Purchase take no body. To end a service plan, use Cancel a subscription, which is described in Subscriptions. List Purchases takes page[size] and page[token].

Catalog items

List catalog items and Get a catalog item return SKUs: id, name, description, category (Insurance, Plan or AddOn), price, currency, interval (OneTime, Monthly or Annual) and isAvailable. A missing SKU returns 404. Use Plans, not catalog items, to decide what an Account can buy.

Webhook events

Purchase lifecycle events are published as webhooks. See Webhooks and events to subscribe.


Did this page help you?