Snooplytics API DocsHome

Payments API

Subscriptions and billing via Stripe

1 min read

Subscription and billing management powered by Stripe. Create checkout sessions for new subscriptions, manage existing subscription plans, handle plan upgrades and downgrades, and access billing portal for payment method updates. Retrieve current subscription status and billing history.

Endpoints

POST
/api/user/organizations/{organizationId}/payments/checkout

Create checkout session

Create a Stripe Checkout session that subscribes the organization to a tier. Optionally bundles slot packs as a second subscription line item.

Bearer TokenScopes: subscription:write, organization:manage-billing

Request

curl -X POST "http://localhost:3030/api/user/organizations/{organizationId}/payments/checkout" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" -d '{"tierId":"plus","interval":"monthly","seatCount":5,"slotPacks":0,"successUrl":"https://app.example.com/success","cancelUrl":"https://app.example.com/cancel"}'

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Body Parameters

NameTypeDescription
tierIdrequiredTierIdTier to subscribe to
plus
intervalrequiredBillingIntervalBilling interval
monthly
seatCountrequirednumberNumber of seats (tier item quantity)
5
slotPacksnumberOptional slot packs to include in the same checkout (added as a second subscription line item).
0
successUrlrequiredstringRedirect URL after successful payment
https://app.example.com/success
cancelUrlrequiredstringRedirect URL if payment is cancelled
https://app.example.com/cancel

Response 200

Checkout session created successfully

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "sessionId": "cs_test_a1b2c3d4e5f6",
  "url": "https://checkout.stripe.com/c/pay/cs_test_..."
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}
POST
/api/user/organizations/{organizationId}/payments/credits/checkout

Create credit pack checkout session

Create a checkout session for purchasing organization credit packs.

Bearer TokenScopes: subscription:write, organization:manage-billing

Request

curl -X POST "http://localhost:3030/api/user/organizations/{organizationId}/payments/credits/checkout" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" -d '{"packId":"credits_100","successUrl":"https://app.example.com/billing?credits=purchased","cancelUrl":"https://app.example.com/billing"}'

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Body Parameters

NameTypeDescription
packIdrequiredCreditPackIdCredit pack ID to purchase
credits_100
successUrlrequiredstringRedirect URL after successful payment
https://app.example.com/billing?credits=purchased
cancelUrlrequiredstringRedirect URL if payment is cancelled
https://app.example.com/billing

Response 200

Checkout session created successfully

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "sessionId": "cs_test_a1b2c3d4e5f6",
  "url": "https://checkout.stripe.com/c/pay/cs_test_..."
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}
POST
/api/user/organizations/{organizationId}/payments/verify

Verify checkout completion

Verify that a checkout session completed successfully. Call this after the user returns from the payment provider.

Bearer TokenScopes: subscription:write

Request

curl -X POST "http://localhost:3030/api/user/organizations/{organizationId}/payments/verify" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" -d '{"sessionId":"cs_test_a1b2c3d4e5f6"}'

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Body Parameters

NameTypeDescription
sessionIdrequiredstringCheckout Session ID from payment provider
cs_test_a1b2c3d4e5f6

Response 200

Payment verification result

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "status": "complete",
  "customerId": "cus_abc123"
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}
GET
/api/user/organizations/{organizationId}/payments/subscription

Get current subscription

Get the organization's current subscription status and details.

Bearer TokenScopes: subscription:read, organization:read

Request

curl -X GET "http://localhost:3030/api/user/organizations/{organizationId}/payments/subscription" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json"

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Response 200

Subscription details retrieved

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "status": "active",
  "interval": "monthly",
  "currentPeriodEnd": "2024-12-31T23:59:59.000Z",
  "cancelAt": null,
  "tierId": {},
  "seatCount": 5,
  "slotPacks": 2
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}
PATCH
/api/user/organizations/{organizationId}/payments/subscription

Update subscription (set-to-value)

Apply any combination of tier, interval, seat count, and slot pack count changes to the active subscription in a single Stripe `subscriptions.update` call. Stripe prorates the in-period delta. The webhook reconciles caps on the org row.

Bearer TokenScopes: subscription:write, organization:manage-billing

Request

curl -X PATCH "http://localhost:3030/api/user/organizations/{organizationId}/payments/subscription" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json" -d '{"tierId":"plus","interval":"monthly","seatCount":0,"slotPacks":0}'

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Body Parameters

NameTypeDescription
tierIdTierIdTier to subscribe to
plus
intervalBillingIntervalBilling interval
monthly
seatCountnumber
slotPacksnumber

Response 200

Subscription updated successfully

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "status": "active",
  "interval": "monthly",
  "currentPeriodEnd": "2024-12-31T23:59:59.000Z",
  "cancelAt": null,
  "tierId": {},
  "seatCount": 5,
  "slotPacks": 2
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}
GET
/api/user/organizations/{organizationId}/payments/subscription/usage

Get subscription usage counts

Returns the live counts the server uses as floors when downsizing the subscription (active members, active projects).

Bearer TokenScopes: subscription:read, organization:read

Request

curl -X GET "http://localhost:3030/api/user/organizations/{organizationId}/payments/subscription/usage" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json"

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Response 200

Usage counts retrieved

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "activeMembers": 4,
  "activeProjects": 12
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}
GET
/api/user/organizations/{organizationId}/payments/portal

Create billing portal session

Create a Stripe Billing Portal session URL for managing payment methods, viewing invoices, or cancelling the subscription.

Bearer TokenScopes: subscription:write, organization:manage-billing

Request

curl -X GET "http://localhost:3030/api/user/organizations/{organizationId}/payments/portal" -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Content-Type: application/json"

Path Parameters

NameTypeDescription
organizationIdrequiredstringOrganization ID
550e8400-e29b-41d4-a716-446655440000

Query Parameters

NameTypeDescription
returnUrlrequiredstringURL to return to after closing the billing portal
https://app.example.com/billing

Response 200

Portal session created successfully

{
"success": true,
"status": 200,
"code": "OK",
"message": "Operation completed successfully",
"data": {
  "url": "https://billing.stripe.com/p/session/test_..."
}
}

Error Responses

401Unauthorized - Invalid or missing authentication

{
"success": false,
"status": 401,
"code": "UNAUTHORIZED",
"message": "Authentication required"
}

403Forbidden - Insufficient permissions

{
"success": false,
"status": 403,
"code": "FORBIDDEN",
"message": "You do not have permission to perform this action"
}