Skip to content

Billing API

The Billing API provides access to your workspace's plan, usage limits, subscription management, and invoices. Synapse uses Lemon Squeezy as its Merchant of Record -- your workspace never touches credit card data directly.

Note

For a user guide on managing billing in the dashboard, see Billing Settings.

Warning

All billing management endpoints (checkout, portal, subscription, invoices) are restricted to the workspace owner. Other roles can view billing status if they have settings:read permission.


Endpoints

MethodPathDescription
GET/v1/workspace/billingGet billing status, usage, and limits
GET/v1/workspace/billing/pricingGet all plans with geo-based pricing
POST/v1/workspace/billing/checkoutCreate a checkout session
GET/v1/workspace/billing/portal-urlGet Lemon Squeezy customer portal URL
GET/v1/workspace/billing/subscriptionGet subscription details
POST/v1/workspace/billing/subscription/pausePause the subscription
POST/v1/workspace/billing/subscription/resumeResume a paused subscription
GET/v1/workspace/billing/invoicesGet invoice history

Get Billing Status

Returns the current plan, usage counters, and limits for the workspace.

bash
curl "https://synapse-api.pyrx.tech/v1/workspace/billing" \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires settings:read permission.

Response

json
{
"plan": "growth",
"status": "active",
"monthly_email_limit": 100000,
"monthly_emails_sent": 24530,
"contacts_limit": 100000,
"contacts_used": 18420,
"members_limit": 15,
"members_used": 4,
"api_keys_limit": 25,
"api_keys_used": 3,
"flows_limit": -1,
"flows_used": 12,
"monthly_events_limit": 1000000,
"monthly_events_used": 156200,
"data_retention_days": 365,
"channels": ["email"],
"ls_current_period_end": "2026-05-20T00:00:00",
"payment_subscription_id": "sub_abc123"
}

Get Pricing Plans

Returns all available plans with geo-based pricing. No authentication required -- this endpoint is used on the public pricing page.

bash
curl "https://synapse-api.pyrx.tech/v1/workspace/billing/pricing"

Auth: None (public endpoint).

Note

Pricing is geo-aware. Synapse reads the CF-IPCountry header set by Cloudflare to determine the visitor's country. Requests from Vietnam (VN) receive VND pricing; all other countries receive USD pricing. Yearly pricing is 10x monthly (2 months free).

Response

json
[
{
"id": "free",
"name": "Free",
"currency": "USD",
"country_code": "US",
"monthly_price": 0,
"yearly_price": 0,
"monthly_formatted": "$0.00",
"yearly_formatted": "$0.00",
"monthly_email_limit": 1000,
"contacts_limit": 1000,
"members_limit": 2,
"flows_limit": 5,
"monthly_events_limit": 10000,
"data_retention_days": 60,
"channels": ["email"],
"custom_domain": false,
"priority_support": false
},
{
"id": "starter",
"name": "Starter",
"currency": "USD",
"country_code": "US",
"monthly_price": 4900,
"yearly_price": 49000,
"monthly_formatted": "$49.00",
"yearly_formatted": "$490.00",
"monthly_email_limit": 10000,
"contacts_limit": 10000,
"members_limit": 3,
"flows_limit": 25,
"monthly_events_limit": 100000,
"data_retention_days": 90,
"channels": ["email"],
"custom_domain": true,
"priority_support": false
},
{
"id": "pro",
"name": "Pro",
"currency": "USD",
"country_code": "US",
"monthly_price": 14900,
"yearly_price": 149000,
"monthly_formatted": "$149.00",
"yearly_formatted": "$1,490.00",
"monthly_email_limit": 50000,
"contacts_limit": 50000,
"members_limit": 5,
"flows_limit": -1,
"monthly_events_limit": 500000,
"data_retention_days": 365,
"channels": ["email"],
"custom_domain": true,
"priority_support": false
},
{
"id": "growth",
"name": "Growth",
"currency": "USD",
"country_code": "US",
"monthly_price": 29900,
"yearly_price": 299000,
"monthly_formatted": "$299.00",
"yearly_formatted": "$2,990.00",
"monthly_email_limit": 100000,
"contacts_limit": 100000,
"members_limit": 15,
"flows_limit": -1,
"monthly_events_limit": 1000000,
"data_retention_days": 365,
"channels": ["email"],
"custom_domain": true,
"priority_support": true
},
{
"id": "enterprise",
"name": "Enterprise",
"currency": "USD",
"country_code": "US",
"monthly_price": 0,
"yearly_price": 0,
"monthly_formatted": "Custom",
"yearly_formatted": "Custom",
"monthly_email_limit": -1,
"contacts_limit": -1,
"members_limit": -1,
"flows_limit": -1,
"monthly_events_limit": -1,
"data_retention_days": -1,
"channels": ["email"],
"custom_domain": true,
"priority_support": true
}
]

VND Pricing Example

When the request originates from Vietnam:

json
{
"id": "starter",
"name": "Starter",
"currency": "VND",
"country_code": "VN",
"monthly_price": 990000,
"yearly_price": 9900000,
"monthly_formatted": "990,000 VND",
"yearly_formatted": "9,900,000 VND"
}

Create Checkout

Creates a Lemon Squeezy checkout session for upgrading to a paid plan.

bash
curl -X POST https://synapse-api.pyrx.tech/v1/workspace/billing/checkout \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "growth",
"billing_interval": "yearly"
}'

Auth: JWT (dashboard). Owner only (billing:read permission).

Request Body

FieldTypeRequiredDescription
plan_idstringYesPlan to purchase: starter, pro, growth, or enterprise
billing_intervalstringNomonthly (default) or yearly

Response (200)

json
{
"checkout_url": "https://pyrx.lemonsqueezy.com/checkout/custom/abc123?signature=xyz",
"subscription_id": null,
"message": "Checkout session created"
}

Redirect the user to checkout_url to complete payment on the Lemon Squeezy hosted checkout page. After payment, the user is redirected back to /settings/billing?upgraded=true.

Error Responses

400 -- Invalid plan:

json
{
"detail": "Plan 'invalid' is not available for purchase"
}

403 -- Not the workspace owner:

json
{
"detail": "Only the workspace owner can access billing"
}

502 -- Payment service unavailable:

json
{
"detail": "Payment service temporarily unavailable"
}

Get Customer Portal URL

Returns a Lemon Squeezy customer portal URL where the owner can manage their subscription, update payment methods, and download invoices.

bash
curl "https://synapse-api.pyrx.tech/v1/workspace/billing/portal-url" \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Owner only (billing:read permission).

Response

json
{
"portal_url": "https://pyrx.lemonsqueezy.com/billing?customer_id=cust_abc123"
}

If the workspace has no Lemon Squeezy customer (never subscribed), portal_url is null.


Get Subscription Details

Returns detailed subscription information including card on file, pause state, and self-service URLs.

bash
curl "https://synapse-api.pyrx.tech/v1/workspace/billing/subscription" \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Owner only (billing:read permission).

Response

json
{
"subscription_id": "sub_abc123",
"status": "active",
"plan": "growth",
"card_brand": "visa",
"card_last_four": "4242",
"is_paused": false,
"renews_at": "2026-05-20T00:00:00Z",
"ends_at": null,
"update_payment_method_url": "https://pyrx.lemonsqueezy.com/subscription/sub_abc123/payment-method",
"customer_portal_url": "https://pyrx.lemonsqueezy.com/billing?customer_id=cust_abc123"
}

Error Response (404)

json
{
"detail": "No active subscription"
}

Pause Subscription

Pauses the current subscription. Billing stops at the end of the current period, but the workspace retains access until the period ends.

bash
curl -X POST https://synapse-api.pyrx.tech/v1/workspace/billing/subscription/pause \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Owner only (billing:read permission).

Response

json
{
"subscription_id": "sub_abc123",
"is_paused": true,
"status": "paused"
}

Resume Subscription

Resumes a previously paused subscription. Billing resumes at the next renewal date.

bash
curl -X POST https://synapse-api.pyrx.tech/v1/workspace/billing/subscription/resume \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Owner only (billing:read permission).

Response

json
{
"subscription_id": "sub_abc123",
"is_paused": false,
"status": "active"
}

Get Invoices

Returns the invoice history for the workspace's subscription.

bash
curl "https://synapse-api.pyrx.tech/v1/workspace/billing/invoices" \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Owner only (billing:read permission).

Response

json
{
"invoices": [
{
"id": "inv_9f8e7d6c",
"status": "paid",
"total": 29900,
"total_formatted": "$299.00",
"currency": "USD",
"created_at": "2026-04-20T00:00:00Z",
"invoice_url": "https://pyrx.lemonsqueezy.com/invoices/inv_9f8e7d6c/download"
},
{
"id": "inv_5a4b3c2d",
"status": "paid",
"total": 29900,
"total_formatted": "$299.00",
"currency": "USD",
"created_at": "2026-03-20T00:00:00Z",
"invoice_url": "https://pyrx.lemonsqueezy.com/invoices/inv_5a4b3c2d/download"
}
]
}

If the workspace has no subscription, returns an empty invoices array.


Plan Limits Reference

PlanEmails/moContactsMembersFlowsEvents/moRetentionCustom DomainPriority Support
Free1,0001,0002510,00060 daysNoNo
Starter10,00010,000325100,00090 daysYesNo
Pro50,00050,0005Unlimited500,0001 yearYesNo
Growth100,000100,00015Unlimited1,000,0001 yearYesYes
EnterpriseUnlimitedUnlimitedUnlimitedUnlimitedUnlimitedUnlimitedYesYes

Exceeding a plan limit returns 403:

json
{
"detail": "Contact limit reached for your plan. Upgrade to add more contacts.",
"code": "plan_limit_reached"
}