Early bird discounts live! Claim your offer

plan.created

A plan is first created on a project.

When this fires

A plan is created through the REST API (POST /api/v1/projects/{project}/plans) or the create_plan MCP tool, or a finished pass season is duplicated into its next season. Plans created from the creator dashboard or the Telegram bot do not emit this event. The plan is immediately eligible for purchase if it was created in the active state.

Required ability

project-subscription-plan:view — token must carry this at mint time to subscribe an endpoint to this event.

Payload

{
  "id": "evt_01HX...",
  "type": "plan.created",
  "created_at": "2026-05-18T10:05:00Z",
  "api_version": "2026-05-01",
  "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
  "data": {
    "plan": {
      "id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b",
      "name": "Premium Monthly",
      "price": "29.00",
      "currency_id": "8f27a0d4-63be-4915-8c07-1a5d9e34b628",
      "billing_cycle": "month",
      "active": true
    }
  }
}

Payload (season duplication)

{
  "id": "evt_01HX...",
  "type": "plan.created",
  "created_at": "2026-05-18T10:05:00Z",
  "api_version": "2026-05-01",
  "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
  "data": {
    "plan_id": "b1a7c3d5-2e48-4f60-9a1b-7c5d3e820f94",
    "plan_name": "Season 4",
    "kind": "pass_series",
    "duplicated_from_plan_id": "c4e82f16-93a7-4d5b-b81c-6e0f27a94d3b"
  }
}

The two shapes are disjoint. The API and MCP path sends data.plan and nothing else; the season-duplication path sends the four flat keys and no data.plan object. Branch on whether data.plan or data.plan_id is present before reading any other field.

Field reference

FieldTypeNotes
idstring ULIDUnique event id, prefixed evt_. Use for idempotent processing.
typestringAlways plan.created for this event.
created_atISO 8601 timestampServer-side emission time.
api_versionstringWebhook API contract version.
project_idstring UUIDProject this event belongs to.
data.planobjectSent by the API and MCP path only; absent when a season is duplicated.
data.plan.idstring UUIDPlan identifier.
data.plan.namestringDisplay name.
data.plan.pricestringDecimal amount as a string, e.g. "29.00".
data.plan.currency_idstring UUIDCurrency row id — not an ISO 4217 code.
data.plan.billing_cycleenum: day | week | month | year | lifetimeBilling cadence unit.
data.plan.activebooleantrue if the plan is purchasable.
data.plan_idstring UUIDSeason-duplication payload only. Plan id of the new season.
data.plan_namestringSeason-duplication payload only. Display name of the new season's plan.
data.kindenum: subscription | pass | pass_seriesSeason-duplication payload only. Always pass_series on this path, since it clones a series.
data.duplicated_from_plan_idstring UUIDSeason-duplication payload only. The plan the season was cloned from.

billing_cycle is only the unit. The multiplier lives in billing_cycle_count on the plan record and is not included in this payload — a "3 month" plan sends billing_cycle: "month" with no indication of the 3. Nor is trial_days. Fetch the plan with GET /v1/projects/{project}/plans/{plan} when you need the full cadence or trial configuration.

Caveats

  • A plan.created event does not imply the plan has been synced to a payment-provider catalog. Listen for plan.sync_completed for that.
  • Trial is configured at create time. A later trial-only edit is only applied — and only then fires plan.updated — when the PATCH also carries a kind key; without it the trial fields are dropped and no event is emitted.

How is this guide?

On this page

Subscriby is a product designed by you — for you.

No boardroom full of executives deciding what we ships next. Our roadmap always shaped by you with your feedback.

Share feedback or a request