Start the trial clock
Stamp the rooftop's Receptionist subscription as activated, which starts the trial countdown. Call it right after the phone number is bought.
Spyne finds the rooftop's current subscription for the product and sets activated_at to now, but only if it is not already set. Calling it again returns the same subscription unchanged, so a retry cannot restart the countdown.
Auth: Bearer token of a signed-in user; the dealer group and rooftop are read from the token · Rate limit: not documented · Processing: synchronous
Before you call it
- Call it after the phone number has been bought.
- Use a token whose rooftop is the one going live. The call has no rooftop parameter.
- If the rooftop has never had a subscription for this product, the call first enrolls it on the product's
freeplan, then stamps it. - If the rooftop had a subscription before that has since ended, for example expired or canceled, the call returns
404. That rule stops a second free trial. - Send an empty JSON object as the body. Fields are not read.
Path parameters
- Headers: set
Authorization: Bearer YOUR_TOKENandContent-Type: application/json. - Body: send an empty JSON object.
- Read
activated_atfrom the response. - If it fails, keep going. The onboarding console treats this step as best-effort.
| Parameter | Type | Required | Description |
|---|---|---|---|
productKey | string | Required | receptionist_agent |
Sample request
curl -X POST "https://api.spyne.ai/agent-marketplace/billing/products/receptionist_agent/subscription/activate" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import requests
res = requests.post(
"https://api.spyne.ai/agent-marketplace/billing/products/receptionist_agent/subscription/activate",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={},
)
print(res.status_code, res.json())const res = await fetch(
'https://api.spyne.ai/agent-marketplace/billing/products/receptionist_agent/subscription/activate',
{
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
}
);
console.log(res.status, await res.json());Sample response
{
"id": "<subscriptionId>",
"product_key": "receptionist_agent",
"plan_key": "<planKey>",
"status": "ACTIVE",
"mrr_minor": "<amount>",
"entitlements": {
"meters": { "<meterKey>": { "limit": null, "period": "MONTH" } },
"features": []
},
"current_period_start": "2026-10-12T15:04:05.000Z",
"current_period_end": null,
"cancel_requested_at": null,
"activated_at": "2026-10-12T15:04:05.000Z"
}{
"message": "Authorization header must be a Bearer token",
"error": "Unauthorized",
"statusCode": 401,
"code": "UNAUTHORIZED"
}{
"code": "TENANT_UNRESOLVED",
"message": "Your account has no enterprise or rooftop associated with it, so this request cannot be scoped.",
"statusCode": 403
}{
"code": "BILLING_SUBSCRIPTION_NOT_FOUND",
"message": "No subscription for this rooftop on this product.",
"statusCode": 404
}{
"code": "BILLING_SUBSCRIPTION_ALREADY_ACTIVE",
"message": "This rooftop already has an active subscription for this product.",
"statusCode": 409
}Response parameters (200)
| Parameter | Type | Description |
|---|---|---|
id | string | Subscription ID. |
product_key | string | receptionist_agent. |
plan_key | string | Current plan key. |
status | string | TRIALING, PENDING, ACTIVE, PAST_DUE, CANCELED or EXPIRED. |
mrr_minor | number | Monthly-normalized recurring amount in minor units. |
entitlements | object | Snapshot of the plan's entitlements. |
current_period_start | string or null | ISO timestamp. |
current_period_end | string or null | ISO timestamp. Billing-cycle end for a recurring plan, or the hard cutoff for a time-boxed plan. null when neither applies. |
cancel_requested_at | string or null | ISO timestamp of a pending cancellation. |
activated_at | string or null | When the product was put into service. The trial countdown starts here. |
Errors
| Status | Code | When it happens |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid Bearer token. |
403 | TENANT_UNRESOLVED | The token has no dealer group or rooftop. |
404 | BILLING_SUBSCRIPTION_NOT_FOUND | The rooftop has no current subscription but had one before. Also returned if a concurrent stamp happened and the subscription can no longer be found. |
404 | BILLING_PRODUCT_NOT_FOUND | Enrollment was needed and the product key does not exist. |
404 | BILLING_PLAN_NOT_FOUND | Enrollment was needed and the product has no free plan. |
409 | BILLING_SUBSCRIPTION_ALREADY_ACTIVE | Enrollment was needed and a parallel request created the subscription first. |
500 | INTERNAL_ERROR | Unexpected error. |
What happens next
Call Grant the live product.
The onboarding console counts the trial as 14 days from activated_at, unless the subscription carries an enforced end date. That count is a screen rule, not something this API enforces.
Updated about 1 hour ago
