Billing
Base URL: https://app.neuroflash.com/api/workspace-service
Manage billing contacts and access the Stripe billing portal.
creates a stripe checkout session with which a customer can create/update the subscription on his workspace to a different price in an embedded modal
POST
/v1/workspaces/{workspaceId}/billing-contacts/{billingContactId}/stripe-checkout-sessionsPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace ID |
billingContactId | string | Yes | BillingContact ID |
Request Body
FieldTypeRequiredDescription
callbackUrlstringYesurl to redirect to after successful checkout.languagestringNolanguage in which to open the checkout session. Defaults to the language of the authenticated customerlegacyPricingPlanIdintegerNodeprecated id of the pricingPlan for which a subscription should be createdpricingPlanIdstringNoResponse
FieldTypeDescription
_embeddedobject
couponobject
_embeddedobject
pricingPlanobject
activebooleanset to true when this pricingPlan can be configured on existing and new subscriptionsbillingIntervalstringcategoryIdstringID of the category this plan belongs todisplayNamestringname used for internal purposes like the admin-ui or hubspot. Should not be displayed to customersidstringid of the pricing planimportedFromLegacyIdintegerisDefaultbooleanIs this the default plan for new customers?priceInEuronumberhow much the customer needs to pay for this subscriptionpricePerCurrencyobjectA map of string keys to float valuesstripeBillingPortalEnabledbooleantrue if subscriptions with this pricingPlan can be self-managed in the stripe billing portalstripePriceIdstringID of the price in stripestripeTrackUsagebooleanwhen true then the usage for subscriptions with this pricingPlan should be tracked in stripetierintegertrialDaysintegerhow many trial days are allowed for this planpricingPlanCategoryobject
displayNamestringidstringtranslationKeystringdiscountPercentagenumberlegacyPricingPlanIdintegerpricingPlanIdstringtranslationKeystringcallbackUrlstringurl to redirect to after successful checkout.languagestringlanguage in which to open the checkout session. Defaults to the language of the authenticated customerlegacyPricingPlanIdintegerdeprecated id of the pricingPlan for which a subscription should be createdpricingPlanIdstringstatusstringstripeClientSecretstringclient secret for this checkout session. Only set directly after creationstripePriceIdstringstripe id of the price from the new subscription that is being checked outstripeSubscriptionIdstringid of the stripe subscription that is being subscribed to in this checkoutExample
- cURL
- Python
- Node.js
- Go
curl -X POST "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}/stripe-checkout-sessions" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"callbackUrl": "string",
"language": "string",
"legacyPricingPlanId": 0,
"pricingPlanId": "string"
}'
import requests
response = requests.post(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}/stripe-checkout-sessions",
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
json={
"callbackUrl": "string",
"language": "string",
"legacyPricingPlanId": 0,
"pricingPlanId": "string"
},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/billing-contacts/${billingContactId}/stripe-checkout-sessions`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"callbackUrl": "string",
"language": "string",
"legacyPricingPlanId": 0,
"pricingPlanId": "string"
}),
}
).then((r) => r.json());
body, _ := json.Marshal(map[string]any{
"callbackUrl": "string",
"language": "string",
"legacyPricingPlanId": 0,
"pricingPlanId": "string",
})
req, _ := http.NewRequest("POST", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/billing-contacts/"+billingContactID+"/stripe-checkout-sessions", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Response:
{
"_embedded": {
"coupon": {
"_embedded": {
"pricingPlan": {
"active": "...",
"billingInterval": "...",
"categoryId": "...",
"displayName": "...",
"id": "...",
"importedFromLegacyId": "...",
"isDefault": "...",
"priceInEuro": "...",
"pricePerCurrency": "...",
"stripeBillingPortalEnabled": "...",
"stripePriceId": "...",
"stripeTrackUsage": "...",
"tier": "...",
"trialDays": "..."
},
"pricingPlanCategory": {
"displayName": "...",
"id": "...",
"translationKey": "..."
}
},
"discountPercentage": 0,
"legacyPricingPlanId": 0,
"pricingPlanId": "string",
"translationKey": "string"
}
},
"callbackUrl": "https://app.neuroflash.com/payment-callback?session_id={CHECKOUT_SESSION_ID}",
"language": "de",
"legacyPricingPlanId": 150,
"pricingPlanId": "string",
"status": "complete",
"stripeClientSecret": "string",
"stripePriceId": "string",
"stripeSubscriptionId": "string"
}
get current billing contact for a workspace
GET
/v1/workspaces/{workspaceId}/billing-contacts/{billingContactId}Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace ID |
Response
FieldTypeDescription
activeDiscountstringreadonly synced from stripe: true if a discount is active for this stripe customeraddressLine1stringreadonly synced from stripe: First line of the address of the billing contactaddressLine2stringreadonly synced from stripe: Second line of the address of the billing contactcitystringreadonly synced from stripe: City of the billing contactcountrystringreadonly synced from stripe: Country of the billing contactcreatedAtstringcreatedByUserIdstringdefaultPaymentCardNumberLastFourDigitsstringdefaultPaymentMethodstringdefaultPaymentMethodCardBrandstringemailstringEmail address of the billing contactidstringimportedFromLegacyCustomerIdintegerDeprecated: only needed while import from legacy api is still active
ID of the legacy customer this was imported fromnamestringName of the billing contactpostalCodestringreadonly synced from stripe: Postal code of the billing contactstatestringreadonly synced from stripe: State of the billing contactstripeCustomerIdstringStripe customer ID for billing purposes. Could become optional if we add other payment providersupdatedAtstringExample
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests
response = requests.get(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}",
headers={"Authorization": f"Bearer {token}"},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/billing-contacts/${billingContactId}`,
{ headers: { Authorization: `Bearer ${token}` } }
).then((r) => r.json());
req, _ := http.NewRequest("GET", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/billing-contacts/"+billingContactID+"", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Response:
{
"activeDiscount": "string",
"addressLine1": "123 Main St",
"addressLine2": "123 Main St",
"city": "Berlin",
"country": "DE",
"createdAt": "2025-01-14T16:20:59Z",
"createdByUserId": "b0920767-2e30-48d3-80ce-268810bc433a",
"defaultPaymentCardNumberLastFourDigits": "1234",
"defaultPaymentMethod": "acss_debit",
"defaultPaymentMethodCardBrand": "amex",
"email": "max.mustermann@neuroflash.com",
"id": "113c0b32-ed6c-4421-b7da-d1faf238eb56",
"importedFromLegacyCustomerId": 12345,
"name": "Max Mustermann",
"postalCode": "12345",
"state": "Schleswig-Holstein",
"stripeCustomerId": "cus_12345abcdef",
"updatedAt": "2025-01-14T16:20:59Z"
}
creates a checkout session in stripe. Checkout sessions can be used to let a customer switch pricing plans with an embedded view which is more convenient than a redirect to the stripe portal
GET
/v1/workspaces/{workspaceId}/billing-contacts/{billingContactId}/stripe-checkout-sessions/{sessionId}Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace ID |
billingContactId | string | Yes | BillingContact ID |
sessionId | string | Yes | stripe session ID |
Response
FieldTypeDescription
_embeddedobject
couponobject
_embeddedobject
pricingPlanobject
activebooleanset to true when this pricingPlan can be configured on existing and new subscriptionsbillingIntervalstringcategoryIdstringID of the category this plan belongs todisplayNamestringname used for internal purposes like the admin-ui or hubspot. Should not be displayed to customersidstringid of the pricing planimportedFromLegacyIdintegerisDefaultbooleanIs this the default plan for new customers?priceInEuronumberhow much the customer needs to pay for this subscriptionpricePerCurrencyobjectA map of string keys to float valuesstripeBillingPortalEnabledbooleantrue if subscriptions with this pricingPlan can be self-managed in the stripe billing portalstripePriceIdstringID of the price in stripestripeTrackUsagebooleanwhen true then the usage for subscriptions with this pricingPlan should be tracked in stripetierintegertrialDaysintegerhow many trial days are allowed for this planpricingPlanCategoryobject
displayNamestringidstringtranslationKeystringdiscountPercentagenumberlegacyPricingPlanIdintegerpricingPlanIdstringtranslationKeystringcallbackUrlstringurl to redirect to after successful checkout.languagestringlanguage in which to open the checkout session. Defaults to the language of the authenticated customerlegacyPricingPlanIdintegerdeprecated id of the pricingPlan for which a subscription should be createdpricingPlanIdstringstatusstringstripeClientSecretstringclient secret for this checkout session. Only set directly after creationstripePriceIdstringstripe id of the price from the new subscription that is being checked outstripeSubscriptionIdstringid of the stripe subscription that is being subscribed to in this checkoutExample
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}/stripe-checkout-sessions/{session_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests
response = requests.get(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}/stripe-checkout-sessions/{session_id}",
headers={"Authorization": f"Bearer {token}"},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/billing-contacts/${billingContactId}/stripe-checkout-sessions/${sessionId}`,
{ headers: { Authorization: `Bearer ${token}` } }
).then((r) => r.json());
req, _ := http.NewRequest("GET", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/billing-contacts/"+billingContactID+"/stripe-checkout-sessions/"+sessionID+"", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Response:
{
"_embedded": {
"coupon": {
"_embedded": {
"pricingPlan": {
"active": "...",
"billingInterval": "...",
"categoryId": "...",
"displayName": "...",
"id": "...",
"importedFromLegacyId": "...",
"isDefault": "...",
"priceInEuro": "...",
"pricePerCurrency": "...",
"stripeBillingPortalEnabled": "...",
"stripePriceId": "...",
"stripeTrackUsage": "...",
"tier": "...",
"trialDays": "..."
},
"pricingPlanCategory": {
"displayName": "...",
"id": "...",
"translationKey": "..."
}
},
"discountPercentage": 0,
"legacyPricingPlanId": 0,
"pricingPlanId": "string",
"translationKey": "string"
}
},
"callbackUrl": "https://app.neuroflash.com/payment-callback?session_id={CHECKOUT_SESSION_ID}",
"language": "de",
"legacyPricingPlanId": 150,
"pricingPlanId": "string",
"status": "complete",
"stripeClientSecret": "string",
"stripePriceId": "string",
"stripeSubscriptionId": "string"
}
Update a billingContact
PUT
/v1/workspaces/{workspaceId}/billing-contacts/{billingContactId}Update a billingContact
Request Body
FieldTypeRequiredDescription
activeDiscountstringNoreadonly synced from stripe: true if a discount is active for this stripe customeraddressLine1stringNoreadonly synced from stripe: First line of the address of the billing contactaddressLine2stringNoreadonly synced from stripe: Second line of the address of the billing contactcitystringNoreadonly synced from stripe: City of the billing contactcountrystringNoreadonly synced from stripe: Country of the billing contactdefaultPaymentCardNumberLastFourDigitsstringNodefaultPaymentMethodstringNodefaultPaymentMethodCardBrandstringNoemailstringYesEmail address of the billing contactnamestringYesName of the billing contactpostalCodestringNoreadonly synced from stripe: Postal code of the billing contactstatestringNoreadonly synced from stripe: State of the billing contactResponse
FieldTypeDescription
activeDiscountstringreadonly synced from stripe: true if a discount is active for this stripe customeraddressLine1stringreadonly synced from stripe: First line of the address of the billing contactaddressLine2stringreadonly synced from stripe: Second line of the address of the billing contactcitystringreadonly synced from stripe: City of the billing contactcountrystringreadonly synced from stripe: Country of the billing contactcreatedAtstringcreatedByUserIdstringdefaultPaymentCardNumberLastFourDigitsstringdefaultPaymentMethodstringdefaultPaymentMethodCardBrandstringemailstringEmail address of the billing contactidstringimportedFromLegacyCustomerIdintegerDeprecated: only needed while import from legacy api is still active
ID of the legacy customer this was imported fromnamestringName of the billing contactpostalCodestringreadonly synced from stripe: Postal code of the billing contactstatestringreadonly synced from stripe: State of the billing contactstripeCustomerIdstringStripe customer ID for billing purposes. Could become optional if we add other payment providersupdatedAtstringExample
- cURL
- Python
- Node.js
- Go
curl -X PUT "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"activeDiscount": "string",
"addressLine1": "string",
"addressLine2": "string",
"city": "string",
"country": "string",
"defaultPaymentCardNumberLastFourDigits": "string",
"defaultPaymentMethod": "string",
"defaultPaymentMethodCardBrand": "string",
"email": "string",
"name": "string",
"postalCode": "string",
"state": "string"
}'
import requests
response = requests.put(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/billing-contacts/{billing_contact_id}",
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
json={
"activeDiscount": "string",
"addressLine1": "string",
"addressLine2": "string",
"city": "string",
"country": "string",
"defaultPaymentCardNumberLastFourDigits": "string",
"defaultPaymentMethod": "string",
"defaultPaymentMethodCardBrand": "string",
"email": "string",
"name": "string",
"postalCode": "string",
"state": "string"
},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/billing-contacts/${billingContactId}`,
{
method: "PUT",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"activeDiscount": "string",
"addressLine1": "string",
"addressLine2": "string",
"city": "string",
"country": "string",
"defaultPaymentCardNumberLastFourDigits": "string",
"defaultPaymentMethod": "string",
"defaultPaymentMethodCardBrand": "string",
"email": "string",
"name": "string",
"postalCode": "string",
"state": "string"
}),
}
).then((r) => r.json());
body, _ := json.Marshal(map[string]any{
"activeDiscount": "string",
"addressLine1": "string",
"addressLine2": "string",
"city": "string",
"country": "string",
"defaultPaymentCardNumberLastFourDigits": "string",
"defaultPaymentMethod": "string",
"defaultPaymentMethodCardBrand": "string",
"email": "string",
"name": "string",
"postalCode": "string",
"state": "string",
})
req, _ := http.NewRequest("PUT", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/billing-contacts/"+billingContactID+"", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Response:
{
"activeDiscount": "string",
"addressLine1": "123 Main St",
"addressLine2": "123 Main St",
"city": "Berlin",
"country": "DE",
"createdAt": "2025-01-14T16:20:59Z",
"createdByUserId": "b0920767-2e30-48d3-80ce-268810bc433a",
"defaultPaymentCardNumberLastFourDigits": "1234",
"defaultPaymentMethod": "acss_debit",
"defaultPaymentMethodCardBrand": "amex",
"email": "max.mustermann@neuroflash.com",
"id": "113c0b32-ed6c-4421-b7da-d1faf238eb56",
"importedFromLegacyCustomerId": 12345,
"name": "Max Mustermann",
"postalCode": "12345",
"state": "Schleswig-Holstein",
"stripeCustomerId": "cus_12345abcdef",
"updatedAt": "2025-01-14T16:20:59Z"
}