Subscriptions
Base URL: https://app.neuroflash.com/api/workspace-service
View the current subscription for a workspace.
get current subscription for a workspace
GET
/v1/workspaces/{workspaceId}/subscriptions/{subscriptionId}Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace ID |
Response
FieldTypeDescription
_embeddedobject
availableWordsintegerdeprecated: remove once the frontend doesn't need it anymore
deprecated, moved to rootLevelnewPricingPlanobject
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 planpricingPlanobject
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
displayNamestringidstringtranslationKeystringactivebooleanFlag indicating whether the subscription is active. Subscriptions can become inactive if they are paused or have more members than the current plan allowsactiveDiscountsarray<string>readonly synced from stripe: true if a discount is active for this stripe subscriptionavailableWordsintegernumber of words that can still be used in this workspace in the current billing period.bonusWordsintegerdeprecated: will be moved to a separate limits table/service. Can currently be managed by admins
Additional bonus words available for usecreatedAtstringcreatedByUserIdstringcurrencystringendDatestringreadonly synced from Stripe: date at which this subscription will automatically be cancelledidstringimportedFromLegacyCustomerIdintegerDeprecated: only needed while import from legacy api is still active
ID of the legacy customer this was imported fromisGracePeriodbooleantrue if the subscription will be cancelled at a set date in the futureisTrialbooleantrue if this is currently a trial periodlimitRenewalDatestringnext date on which the limits (like words available, images available etc) will be reset. This happens every month, starting with the start of the subscriptionnextSubscriptionCycleStartstringreadonly synced from Stripe: Timestamp when the next billing cycle starts. This is NOT necessarily the timestamp when we reset the limits in our system because we reset them monthly even if this is a yearly planpaymentCardNumberLastFourDigitsstringreadonly synced from Stripe: Last four digits of the payment card number. Uses the default payment on the subscription with a fallback to the payment from the last invoicepaymentMethodCardBrandstringpaymentPausedbooleanreadonly synced from Stripe: true if the payment collection for this subscription is currently paused. Even though stripe intends these subscription to stay active
and just be free for a while, we treat subscriptions with payment paused as inactivepaymentTypestringpricingPlanIdstringpricingPlanWordsintegerdeprecated: these fields are managed internally but will be moved to the limit structure
deprecated: will be moved to a separate limits table/service
how many words the pricingPlan from this subscription allows.sepaPaymentFailedbooleanreadonly synced from Stripe: Flag indicating whether the SEPA payment has failedspilloverWordsintegerdeprecated: will be moved to a separate limits table/service. Used to calculate the available words next month because you can only keep overspilled words from last month, not accumulate them over multiple months
Words carried over from previous monthstripeStatusstringstripeSubscriptionIdstringStripe subscription IDstripeSubscriptionItemIdstringID of the subscription item in stripe (subscriptions should only have one item)trialEndsAtstringreadonly synced from Stripe: Timestamp when the trial period endstrialStartedAtstringreadonly synced from stripe: if a trial is in progress, date when it startedupdatedAtstringusedWordsintegerdeprecated: will be moved to a separate limits table/service
How many words were used in this workspace in the current monthworkspaceIdstringID of the workspace this subscription belongs toExample
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/subscriptions/{subscription_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests
response = requests.get(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/subscriptions/{subscription_id}",
headers={"Authorization": f"Bearer {token}"},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/subscriptions/${subscriptionId}`,
{ headers: { Authorization: `Bearer ${token}` } }
).then((r) => r.json());
req, _ := http.NewRequest("GET", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/subscriptions/"+subscriptionID+"", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Response:
{
"_embedded": {
"availableWords": 500,
"newPricingPlan": {
"active": false,
"billingInterval": "day",
"categoryId": "18d0035a-5850-4bf4-8d5d-3dc8684e2bb2",
"displayName": "Business Pro with 3 members",
"id": "18d0045a-5850-4bf4-8d5d-3dc8684e2bb2",
"importedFromLegacyId": 0,
"isDefault": true,
"priceInEuro": 24.5,
"pricePerCurrency": {},
"stripeBillingPortalEnabled": false,
"stripePriceId": "price_123",
"stripeTrackUsage": false,
"tier": 5,
"trialDays": 7
},
"pricingPlan": {
"active": false,
"billingInterval": "day",
"categoryId": "18d0035a-5850-4bf4-8d5d-3dc8684e2bb2",
"displayName": "Business Pro with 3 members",
"id": "18d0045a-5850-4bf4-8d5d-3dc8684e2bb2",
"importedFromLegacyId": 0,
"isDefault": true,
"priceInEuro": 24.5,
"pricePerCurrency": {},
"stripeBillingPortalEnabled": false,
"stripePriceId": "price_123",
"stripeTrackUsage": false,
"tier": 5,
"trialDays": 7
},
"pricingPlanCategory": {
"displayName": "string",
"id": "string",
"translationKey": "string"
}
},
"active": true,
"activeDiscounts": [
"string"
],
"availableWords": 500,
"bonusWords": 1000,
"createdAt": "2025-01-14T16:20:59Z",
"createdByUserId": "b0920767-2e30-48d3-80ce-268810bc433a",
"currency": "aed",
"endDate": "string",
"id": "113c0b32-ed6c-4421-b7da-d1faf238eb56",
"importedFromLegacyCustomerId": 12345,
"isGracePeriod": false,
"isTrial": false,
"limitRenewalDate": "string",
"nextSubscriptionCycleStart": "2024-01-01T00:00:00Z",
"paymentCardNumberLastFourDigits": "4242",
"paymentMethodCardBrand": "amex",
"paymentPaused": false,
"paymentType": "acss_debit",
"pricingPlanId": "18d0045a-5850-4bf4-8d5d-3dc8684e2bb2",
"pricingPlanWords": 10000,
"sepaPaymentFailed": false,
"spilloverWords": 500,
"stripeStatus": "active",
"stripeSubscriptionId": "sub_12345abcdef",
"stripeSubscriptionItemId": "sub_item_ad909w0",
"trialEndsAt": "2023-12-31T23:59:59Z",
"trialStartedAt": "string",
"updatedAt": "2025-01-14T16:20:59Z",
"usedWords": 5000,
"workspaceId": "550e8400-e29b-41d4-a716-446655440000"
}
Update a subscription
PUT
/v1/workspaces/{workspaceId}/subscriptions/{subscriptionId}Update a subscription
Request Body
FieldTypeRequiredDescription
bonusWordsintegerNodeprecated: will be moved to a separate limits table/service. Can currently be managed by admins
Additional bonus words available for uselimitRenewalDatestringNonext date on which the limits (like words available, images available etc) will be reset. This happens every month, starting with the start of the subscriptionpricingPlanIdstringNoExample
- cURL
- Python
- Node.js
- Go
curl -X PUT "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/subscriptions/{subscription_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string"
}'
import requests
response = requests.put(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/subscriptions/{subscription_id}",
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
json={
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string"
},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/subscriptions/${subscriptionId}`,
{
method: "PUT",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string"
}),
}
).then((r) => r.json());
body, _ := json.Marshal(map[string]any{
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string",
})
req, _ := http.NewRequest("PUT", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/subscriptions/"+subscriptionID+"", 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()
Patch a subscription
PATCH
/v1/workspaces/{workspaceId}/subscriptions/{subscriptionId}Patch a subscription
Request Body
FieldTypeRequiredDescription
bonusWordsintegerNodeprecated: will be moved to a separate limits table/service. Can currently be managed by admins
Additional bonus words available for uselimitRenewalDatestringNonext date on which the limits (like words available, images available etc) will be reset. This happens every month, starting with the start of the subscriptionpricingPlanIdstringNoExample
- cURL
- Python
- Node.js
- Go
curl -X PATCH "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/subscriptions/{subscription_id}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string"
}'
import requests
response = requests.patch(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/subscriptions/{subscription_id}",
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
json={
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string"
},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/subscriptions/${subscriptionId}`,
{
method: "PATCH",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string"
}),
}
).then((r) => r.json());
body, _ := json.Marshal(map[string]any{
"bonusWords": 0,
"limitRenewalDate": "string",
"pricingPlanId": "string",
})
req, _ := http.NewRequest("PATCH", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/subscriptions/"+subscriptionID+"", 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()
update number of used words in a workspace
POST
/v1/workspaces/{workspaceId}/current-subscription/word-usage-incrementsPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace ID |
Request Body
FieldTypeRequiredDescription
amountintegerNonegative values are ignored. To add words you need to increase bonus words.Example
- cURL
- Python
- Node.js
- Go
curl -X POST "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/current-subscription/word-usage-increments" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"amount": 0
}'
import requests
response = requests.post(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/current-subscription/word-usage-increments",
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
json={
"amount": 0
},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/current-subscription/word-usage-increments`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"amount": 0
}),
}
).then((r) => r.json());
body, _ := json.Marshal(map[string]any{
"amount": 0,
})
req, _ := http.NewRequest("POST", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/current-subscription/word-usage-increments", 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()
get current subscription for a workspace
GET
/v1/workspaces/{workspaceId}/current-subscriptionPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace ID |
Response
FieldTypeDescription
_embeddedobject
availableWordsintegerdeprecated: remove once the frontend doesn't need it anymore
deprecated, moved to rootLevelnewPricingPlanobject
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 planpricingPlanobject
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
displayNamestringidstringtranslationKeystringactivebooleanFlag indicating whether the subscription is active. Subscriptions can become inactive if they are paused or have more members than the current plan allowsactiveDiscountsarray<string>readonly synced from stripe: true if a discount is active for this stripe subscriptionavailableWordsintegernumber of words that can still be used in this workspace in the current billing period.bonusWordsintegerdeprecated: will be moved to a separate limits table/service. Can currently be managed by admins
Additional bonus words available for usecreatedAtstringcreatedByUserIdstringcurrencystringendDatestringreadonly synced from Stripe: date at which this subscription will automatically be cancelledidstringimportedFromLegacyCustomerIdintegerDeprecated: only needed while import from legacy api is still active
ID of the legacy customer this was imported fromisGracePeriodbooleantrue if the subscription will be cancelled at a set date in the futureisTrialbooleantrue if this is currently a trial periodlimitRenewalDatestringnext date on which the limits (like words available, images available etc) will be reset. This happens every month, starting with the start of the subscriptionnextSubscriptionCycleStartstringreadonly synced from Stripe: Timestamp when the next billing cycle starts. This is NOT necessarily the timestamp when we reset the limits in our system because we reset them monthly even if this is a yearly planpaymentCardNumberLastFourDigitsstringreadonly synced from Stripe: Last four digits of the payment card number. Uses the default payment on the subscription with a fallback to the payment from the last invoicepaymentMethodCardBrandstringpaymentPausedbooleanreadonly synced from Stripe: true if the payment collection for this subscription is currently paused. Even though stripe intends these subscription to stay active
and just be free for a while, we treat subscriptions with payment paused as inactivepaymentTypestringpricingPlanIdstringpricingPlanWordsintegerdeprecated: these fields are managed internally but will be moved to the limit structure
deprecated: will be moved to a separate limits table/service
how many words the pricingPlan from this subscription allows.sepaPaymentFailedbooleanreadonly synced from Stripe: Flag indicating whether the SEPA payment has failedspilloverWordsintegerdeprecated: will be moved to a separate limits table/service. Used to calculate the available words next month because you can only keep overspilled words from last month, not accumulate them over multiple months
Words carried over from previous monthstripeStatusstringstripeSubscriptionIdstringStripe subscription IDstripeSubscriptionItemIdstringID of the subscription item in stripe (subscriptions should only have one item)trialEndsAtstringreadonly synced from Stripe: Timestamp when the trial period endstrialStartedAtstringreadonly synced from stripe: if a trial is in progress, date when it startedupdatedAtstringusedWordsintegerdeprecated: will be moved to a separate limits table/service
How many words were used in this workspace in the current monthworkspaceIdstringID of the workspace this subscription belongs toExample
- cURL
- Python
- Node.js
- Go
curl "https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/current-subscription" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests
response = requests.get(
f"https://app.neuroflash.com/api/workspace-service/v1/workspaces/{workspace_id}/current-subscription",
headers={"Authorization": f"Bearer {token}"},
).json()
const response = await fetch(
`https://app.neuroflash.com/api/workspace-service/v1/workspaces/${workspaceId}/current-subscription`,
{ headers: { Authorization: `Bearer ${token}` } }
).then((r) => r.json());
req, _ := http.NewRequest("GET", "https://app.neuroflash.com/api/workspace-service/v1/workspaces/"+workspaceID+"/current-subscription", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Response:
{
"_embedded": {
"availableWords": 500,
"newPricingPlan": {
"active": false,
"billingInterval": "day",
"categoryId": "18d0035a-5850-4bf4-8d5d-3dc8684e2bb2",
"displayName": "Business Pro with 3 members",
"id": "18d0045a-5850-4bf4-8d5d-3dc8684e2bb2",
"importedFromLegacyId": 0,
"isDefault": true,
"priceInEuro": 24.5,
"pricePerCurrency": {},
"stripeBillingPortalEnabled": false,
"stripePriceId": "price_123",
"stripeTrackUsage": false,
"tier": 5,
"trialDays": 7
},
"pricingPlan": {
"active": false,
"billingInterval": "day",
"categoryId": "18d0035a-5850-4bf4-8d5d-3dc8684e2bb2",
"displayName": "Business Pro with 3 members",
"id": "18d0045a-5850-4bf4-8d5d-3dc8684e2bb2",
"importedFromLegacyId": 0,
"isDefault": true,
"priceInEuro": 24.5,
"pricePerCurrency": {},
"stripeBillingPortalEnabled": false,
"stripePriceId": "price_123",
"stripeTrackUsage": false,
"tier": 5,
"trialDays": 7
},
"pricingPlanCategory": {
"displayName": "string",
"id": "string",
"translationKey": "string"
}
},
"active": true,
"activeDiscounts": [
"string"
],
"availableWords": 500,
"bonusWords": 1000,
"createdAt": "2025-01-14T16:20:59Z",
"createdByUserId": "b0920767-2e30-48d3-80ce-268810bc433a",
"currency": "aed",
"endDate": "string",
"id": "113c0b32-ed6c-4421-b7da-d1faf238eb56",
"importedFromLegacyCustomerId": 12345,
"isGracePeriod": false,
"isTrial": false,
"limitRenewalDate": "string",
"nextSubscriptionCycleStart": "2024-01-01T00:00:00Z",
"paymentCardNumberLastFourDigits": "4242",
"paymentMethodCardBrand": "amex",
"paymentPaused": false,
"paymentType": "acss_debit",
"pricingPlanId": "18d0045a-5850-4bf4-8d5d-3dc8684e2bb2",
"pricingPlanWords": 10000,
"sepaPaymentFailed": false,
"spilloverWords": 500,
"stripeStatus": "active",
"stripeSubscriptionId": "sub_12345abcdef",
"stripeSubscriptionItemId": "sub_item_ad909w0",
"trialEndsAt": "2023-12-31T23:59:59Z",
"trialStartedAt": "string",
"updatedAt": "2025-01-14T16:20:59Z",
"usedWords": 5000,
"workspaceId": "550e8400-e29b-41d4-a716-446655440000"
}