All endpoints require:

  • Authorization: Bearer <merchant_api_token>
  • Content-Type: application/json
  • Idempotency-Key on mutating calls

Customer-level subscription lifecycle (pause, cancel, etc.) is managed in the merchant dashboard and is not part of this public API.


Create Plan

POST /v1/plans
Idempotency-Key: <uuid-v4>

Body

{
  "name": "Monthly Lens Supply",
  "interval": "monthly",          // monthly · quarterly · yearly
  "price_cents": 2500,
  "currency": "usd",
  "trial_days": 14
}

Success 201

{
  "plan_id": "plan_123",
  "name": "Monthly Lens Supply",
  "interval": "monthly",
  "price_cents": 2500,
  "currency": "usd",
  "trial_days": 14,
  "status": "ACTIVE",
  "created_at": "2025-06-05T12:00:00Z"
}

List Plans

GET /v1/plans
Authorization: Bearer <merchant_api_token>

Optional query: status=ACTIVE|ARCHIVED.


Retrieve a Plan

GET /v1/plans/{plan_id}
Authorization: Bearer <merchant_api_token>

Update Plan

PUT /v1/plans/{plan_id}
Idempotency-Key: <uuid-v4>

Send only the fields you’re changing.


Archive Plan

DELETE /v1/plans/{plan_id}
Authorization: Bearer <merchant_api_token>

Returns 204 No Content. Archiving blocks new checkouts but leaves existing subscribers intact.


Attach Plan(s) to a Product

Attach one or many plans in a single call.

POST /v1/products/{product_id}/attach-plans
Idempotency-Key: <uuid-v4>

Body

{
  "plan_ids": ["plan_123", "plan_456"]
}

Success 200

{
  "product_id": "prod_abc123",
  "attached_plan_ids": ["plan_123", "plan_456"]
}

Detach Plan(s) from a Product

Remove one or more plans without affecting the rest.

POST /v1/products/{product_id}/detach-plans
Idempotency-Key: <uuid-v4>

Body

{
  "plan_ids": ["plan_123"]
}

Success 200

{
  "product_id": "prod_abc123",
  "attached_plan_ids": ["plan_456"]
}

Plan Status Values

StatusMeaning
ACTIVEPlan is available for new sign-ups
ARCHIVEDHidden from checkout; active subscribers unaffected