Plan and Checkout Reference

Request and response contracts for service plans and Stripe checkout sessions.

AuthOS release 0.8.2 API v1 Latest-only documentation
Updated Jul 15, 2026
On this page

Plan Management

POST /api/organizations/:org_slug/services/:service_slug/plans

Create a new subscription plan for a service.

Permissions: Owner or Admin

Headers:

Header Value
Authorization Bearer {jwt}

Path Parameters:

Parameter Type Description
org_slug string Organization slug
service_slug string Service slug

Request Body:

Field Type Required Description
name string Yes Plan name (e.g., “Pro”, “Enterprise”)
description string No Optional plan description
price_cents integer Yes Price in cents (e.g., 1999 for $19.99)
currency string Yes Currency code (e.g., “usd”, “eur”)
features string[] No List of features included in the plan
stripe_price_id string No Optional Stripe price ID for billing
is_default boolean No Whether this is the default plan for the service (default: false)

Example Request:

curl -X POST https://sso.example.com/api/organizations/acme-corp/services/main-app/plans \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pro",
    "price_cents": 1999,
    "currency": "usd",
    "features": ["Advanced analytics", "Priority support", "Custom branding"]
  }'

Example Response (200 OK):

{
  "plan": {
    "id": "plan-uuid",
    "service_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Pro",
    "price_cents": 1999,
    "currency": "usd",
    "features": ["Advanced analytics", "Priority support", "Custom branding"],
    "created_at": "2025-01-15T10:30:00Z"
  },
  "subscription_count": 0
}

Error Responses:

  • 401 Unauthorized: Invalid or missing JWT
  • 403 Forbidden: User is not an owner or admin
  • 404 Not Found: Organization or service not found
  • 500 Internal Server Error: Database error

Notes:

  • Price is stored in cents to avoid floating-point precision issues
  • Features array is optional and can be empty
  • New plans start with zero subscriptions
  • Currency should be ISO 4217 code (lowercase)
  • Plans can be used immediately after creation

GET /api/organizations/:org_slug/services/:service_slug/plans

List all plans for a service.

Permissions: Member

Headers:

Header Value
Authorization Bearer {jwt}

Path Parameters:

Parameter Type Description
org_slug string Organization slug
service_slug string Service slug

Example Request:

curl -X GET https://sso.example.com/api/organizations/acme-corp/services/main-app/plans \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Example Response (200 OK):

[
  {
    "plan": {
      "id": "free-plan-uuid",
      "service_id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Free",
      "price_cents": 0,
      "currency": "usd",
      "features": [],
      "created_at": "2025-01-15T10:30:00Z"
    },
    "subscription_count": 350
  },
  {
    "plan": {
      "id": "pro-plan-uuid",
      "service_id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Pro",
      "price_cents": 1999,
      "currency": "usd",
      "features": ["Advanced analytics", "Priority support", "Custom branding"],
      "created_at": "2025-01-15T11:00:00Z"
    },
    "subscription_count": 75
  }
]

Error Responses:

  • 401 Unauthorized: Invalid or missing JWT
  • 403 Forbidden: User is not a member
  • 404 Not Found: Organization or service not found
  • 500 Internal Server Error: Database error

Notes:

  • Returns all plans for the service
  • Each plan includes active subscription count
  • Plans are not ordered (consider sorting by price or name on client)
  • All members can view plans

PATCH /api/organizations/:org_slug/services/:service_slug/plans/:plan_id

Update a subscription plan.

Permissions: Owner or Admin

Headers:

Header Value
Authorization Bearer {jwt}

Path Parameters:

Parameter Type Description
org_slug string Organization slug
service_slug string Service slug
plan_id string Plan ID (UUID)

Request Body:

Field Type Required Description
name string No New plan name
price_cents integer No New price in cents
currency string No New currency code
features string[] No Updated features list

Example Request:

curl -X PATCH https://sso.example.com/api/organizations/acme-corp/services/main-app/plans/plan-uuid \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "price_cents": 2499,
    "features": ["Advanced analytics", "Priority support", "Custom branding", "API access"]
  }'

Example Response (200 OK):

{
  "plan": {
    "id": "plan-uuid",
    "service_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Pro",
    "price_cents": 2499,
    "currency": "usd",
    "features": ["Advanced analytics", "Priority support", "Custom branding", "API access"],
    "created_at": "2025-01-15T10:30:00Z"
  },
  "subscription_count": 75
}

Error Responses:

  • 400 Bad Request: No fields to update or plan belongs to different service
  • 401 Unauthorized: Invalid or missing JWT
  • 403 Forbidden: User is not an owner or admin
  • 404 Not Found: Organization, service, or plan not found
  • 500 Internal Server Error: Database error

Notes:

  • All fields are optional - only provided fields are updated
  • At least one field must be provided
  • Features array replaces existing features (not merged)
  • Price changes affect new subscriptions only (existing subscriptions keep their price)
  • Changes take effect immediately

DELETE /api/organizations/:org_slug/services/:service_slug/plans/:plan_id

Delete a subscription plan.

Permissions: Owner or Admin

Headers:

Header Value
Authorization Bearer {jwt}

Path Parameters:

Parameter Type Description
org_slug string Organization slug
service_slug string Service slug
plan_id string Plan ID (UUID)

Example Request:

curl -X DELETE https://sso.example.com/api/organizations/acme-corp/services/main-app/plans/plan-uuid \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Example Response (204 No Content):

No response body.

Error Responses:

  • 400 Bad Request: Plan has active subscriptions (must be cancelled first)
  • 401 Unauthorized: Invalid or missing JWT
  • 403 Forbidden: User is not an owner or admin
  • 404 Not Found: Organization, service, or plan not found
  • 500 Internal Server Error: Database error

Notes:

  • This is a destructive operation that cannot be undone
  • Plan cannot be deleted if it has active subscriptions
  • Consider archiving instead of deleting plans with historical subscriptions
  • Users on this plan will need to be migrated to a different plan first

Subscription & Checkout

POST /api/organizations/:org_slug/services/:service_slug/checkout

Creates a Stripe checkout session for the authenticated user to subscribe to a plan.

Permissions: Any organization member

Headers:

Header Value
Authorization Bearer {jwt}
Content-Type application/json

Path Parameters:

Parameter Type Description
org_slug string Organization slug
service_slug string Service slug

Request Body:

Field Type Required Description
plan_id string Yes The plan ID to subscribe to
success_url string Yes URL to redirect after successful checkout. Use {CHECKOUT_SESSION_ID} placeholder to include session ID
cancel_url string Yes URL to redirect if checkout is cancelled

Example Request:

curl -X POST https://sso.example.com/api/organizations/acme-corp/services/main-app/checkout \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "plan_id": "550e8400-e29b-41d4-a716-446655440000",
    "success_url": "https://app.acme.com/billing/success?session_id={CHECKOUT_SESSION_ID}",
    "cancel_url": "https://app.acme.com/billing/cancel"
  }'

Success Response (200 OK):

{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_a1b2c3d4e5f6g7h8i9j0...",
  "session_id": "cs_test_a1b2c3d4e5f6g7h8i9j0"
}

Error Responses:

  • 400 Bad Request: Plan not found, plan has no Stripe price, or plan doesn’t belong to service
  • 401 Unauthorized: Missing or invalid JWT token
  • 403 Forbidden: User is not a member of the organization
  • 404 Not Found: Organization or service not found
  • 500 Internal Server Error: Stripe API error or missing checkout URL

Notes:

  • Organization Membership Required: User must be a member of the organization
  • Active Organization: Organization must be in active status (not suspended or pending)
  • Stripe Price Required: Plans must have a stripe_price_id configured to be purchasable
  • Automatic Customer Creation: Stripe customers are automatically created per organization
  • Metadata Tracking: Subscription metadata includes user_id, service_id, plan_id, and org_id