Skip to main content

Subscriptions

GET Get current subscription​

https://focus.toggl.com/api/organizations/{organization_id}/subscriptions/current

Get current subscription.

curl  https://focus.toggl.com/api/organizations/{organization_id}/subscriptions/current \
-H "Content-Type: application/json"

Parameters​

Path​

nametyperequireddescription
organization_idintegertrueorganization ID

Response​

200​

NameTypeDescription
defers_commitment_reductionsbooleanDefersCommitmentReductions is omitted when a plan-tier downgrade or a switch to a shorter billing period on this subscription applies immediately. When true, such a reduction may take effect at the end of the current period instead: the feature is on and the subscription is an active, paid annual commitment that is not cancelling. The plan change can still apply immediately, or be refused, for reasons specific to the request (seats added in the same change, a module add-on on the same product, another product's scheduled change), so deferred on the plan change response is the authority on what happened.
focus_trial_ended_atstringnull
grantedbooleanGranted reports an entitlement the organization holds without paying for it: the Stripe-backed fields are empty because no Stripe subscription backs the grant.
organization_idinteger-
priceobject-
productobject-
subscriptionobject-
subscription_itemobject-
track_subscriptionobject-
price​
NameTypeDescription
billing_period_in_monthsinteger-
cost_in_centsinteger-
currencystring-
tagstring-
track_pricing_plan_idinteger-
product​
NameTypeDescription
handlestring-
namestring-
sitestring-
toggl_product_idstring-
track_enterpriseboolean-
track_plan_idinteger-
subscription​
NameTypeDescription
customerobject-
grant_source_subscription_idstringGrantSourceSubscriptionID is the paid Stripe subscription whose plan grants it.
grantedbooleanGranted reports a product the organization holds through another product's paid plan; no Stripe subscription backs it.
idstring-
payment_failedboolean-
statestring-
subscription_itemobject-
urlstring-
customer​
NameTypeDescription
idstring-
urlstring-
subscription_item​
NameTypeDescription
discountobject-
quantityintegerQuantity is the live paid quantity (number of paid licenses).
scheduled_changeobjectScheduledChange describes a plan or cadence change deferred to the end of the current period; nil when no plan change is pending.
scheduled_quantityintegerScheduledQuantity is the scheduled next-cycle quantity when a change is pending in Stripe (typically a decrease); nil when there is no pending change — no schedule, or the scheduled quantity equals the live quantity.
subscription_item_idstringID is the Stripe subscription item ID. Empty for trial-only synthetic responses where no Stripe subscription item exists yet.
updated_atstring-
discount​
NameTypeDescription
amount_offinteger-
coupon_idstring-
currencystring-
durationstring-
duration_in_monthsintegerDurationInMonths is the coupon's month count for a repeating discount; nil otherwise.
ends_atstringEndsAt is when the discount stops applying (RFC3339); nil when it has no end.
namestring-
percent_offnumber-
promotion_code_idstring-
scheduled_change​
NameTypeDescription
billing_period_in_monthsintegerBillingPeriodInMonths is the new price's billing period (1 = monthly, 12 = annual).
cost_in_centsintegerCostInCents is the new price's per-seat cost.
effective_atstringEffectiveAt is the date the change applies (the current period end), YYYY-MM-DD.
pricing_plan_tagstringPricingPlanTag is the tag of the price the subscription moves to at period end.
subscription_item​
NameTypeDescription
discountobject-
quantityintegerQuantity is the live paid quantity (number of paid licenses).
scheduled_changeobjectScheduledChange describes a plan or cadence change deferred to the end of the current period; nil when no plan change is pending.
scheduled_quantityintegerScheduledQuantity is the scheduled next-cycle quantity when a change is pending in Stripe (typically a decrease); nil when there is no pending change — no schedule, or the scheduled quantity equals the live quantity.
subscription_item_idstringID is the Stripe subscription item ID. Empty for trial-only synthetic responses where no Stripe subscription item exists yet.
updated_atstring-
discount​
NameTypeDescription
amount_offinteger-
coupon_idstring-
currencystring-
durationstring-
duration_in_monthsintegerDurationInMonths is the coupon's month count for a repeating discount; nil otherwise.
ends_atstringEndsAt is when the discount stops applying (RFC3339); nil when it has no end.
namestring-
percent_offnumber-
promotion_code_idstring-
scheduled_change​
NameTypeDescription
billing_period_in_monthsintegerBillingPeriodInMonths is the new price's billing period (1 = monthly, 12 = annual).
cost_in_centsintegerCostInCents is the new price's per-seat cost.
effective_atstringEffectiveAt is the date the change applies (the current period end), YYYY-MM-DD.
pricing_plan_tagstringPricingPlanTag is the tag of the price the subscription moves to at period end.
track_subscription​
NameTypeDescription
cancel_datestring-
current_period_ends_atstring-
current_period_starts_atstring-
end_datestring-
pause_eligiblebooleanPauseEligible reports whether a pause request would be accepted right now. It is a strong hint computed from stored data, not a promise. The pause endpoint stays authoritative: the one rule it applies that is missing here is pending invoice items, which costs a Stripe call to see and has no place on a cached read path. PauseIneligibleReason names the rule that failed, as a stable code for clients to map to their own copy, and is nil while PauseEligible is true.
pause_ineligible_reasonstringValid values: already_used, already_paused, not_monthly, trialing, not_active, cancel_scheduled, not_card, discount_scheduled, unsupported_pause.
pause_starts_atstring-
pausedbooleanPaused is true while the organization is in the unpaid months of a self-serve pause, which is when products make it read-only; the subscription itself stays "active". PauseStartsAt is the first skipped renewal, where those months start, and ResumesAt the renewal billing restarts at. Both are set from the moment the pause applies until billing restarts or the customer resumes, so clients can show a pause that has not started yet.
payment_failedboolean-
resumablebooleanResumable is true while a self-serve pause is open, which is when a resume request has something to act on. It is false for a collection pause applied from the Stripe Dashboard or by support: those are not self-serve pauses and the resume endpoint does not lift them.
resumes_atstring-
start_datestring-
subscription_created_atstring-
subscription_updated_atstring-
trialobject-
trial​
NameTypeDescription
availableboolean-
end_datestring-
start_datestring-
trial_plan_idinteger-

204​

No subscription and no plan

400​

Invalid request

403​

Insufficient permissions

500​

Internal Server Error

GET Get current trial​

https://focus.toggl.com/api/organizations/{organization_id}/subscriptions/trials/current

Get the organization's current active Focus plan trial. Add-on module trials (Capacity, Time Off) are excluded: they run alongside the organization's own plan rather than standing in for it.

curl  https://focus.toggl.com/api/organizations/{organization_id}/subscriptions/trials/current \
-H "Content-Type: application/json"

Parameters​

Path​

nametyperequireddescription
organization_idintegertrueorganization ID

Response​

200​

Current active trial

NameTypeDescription
auto_upgradeboolean-
auto_upgrade_notified_atstringAutoUpgradeNotifiedAt is when the trial-ending notice was last sent, if ever.
idinteger-
organization_idinteger-
plan_idinteger-
plan_namestring-
product_handlestring-
toggl_product_namestring-
trial_cancels_atstring-
trial_created_atstring-
trial_deleted_atstring-
trial_ended_atstring-
trial_started_atstring-
trial_typestring-

204​

No active trial found

400​

Invalid request

404​

Subscription not found

500​

Internal server error

POST Upserts a trial​

https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/subscriptions/upsert-forced-trial

Creates or updates a trial for the organization based on workspace data and Plan import history.

curl -X POST https://focus.toggl.com/api/organizations/{organization_id}/workspaces/{workspace_id}/subscriptions/upsert-forced-trial \
-H "Content-Type: application/json" \
-d '\{"plan_workspace_id":"integer"\}'

Parameters​

Path​

nametyperequireddescription
organization_idintegertrueorganization ID
workspace_idintegertrueworkspace ID

Body​

NameTypeDescription
plan_workspace_idinteger-

Response​

200​

Trial was created or updated

NameTypeDescription
auto_upgradeboolean-
auto_upgrade_notified_atstringAutoUpgradeNotifiedAt is when the trial-ending notice was last sent, if ever.
idinteger-
organization_idinteger-
plan_idinteger-
plan_namestring-
product_handlestring-
toggl_product_namestring-
trial_cancels_atstring-
trial_created_atstring-
trial_deleted_atstring-
trial_ended_atstring-
trial_started_atstring-
trial_typestring-

204​

No trial created or updated (existing unchanged trial, paid subscription, or no eligible trial)

400​

Invalid request

409​

Forced trial already exists or org has active subscription

500​

Internal server error

© 2026 Toggl. All rights reserved.