Skip to content

List the partner's plans (partner-api)

Lists the plans your partner can see: its own plans and the global Voxbi plans, ordered by sort_order then name (the same plans as the Plans page in the partner portal). Plans of other partners are never returned. Each plan carries its countries; an empty list means the plan is offered in every country.

Pass country to get only the plans a visitor from that country can choose from: plans linked to the country plus plans linked to no country. To get every country with its plans in one call, use GET /plans/countries.

Required scopes: partner-api and partner-plans.

Query parameters: country, active, search (matches name and description), per_page (1 to 5000, default 100) and page. Returned as a Laravel paginator: data, links and meta.

HTTP: PartnerApiKey

Partner API key. A bearer token that a Reseller Admin generates in the partner portal under Settings, API keys. It belongs to the reseller partner, not to a person, and carries the scopes ticked at creation time. Send it on every request as Authorization: Bearer <partner_api_key>.

Every response is confined to the partner the key belongs to. Keep the key secret and call the API from your server only, never from a browser app.

HTTP Authorization Scheme
bearer
Bearer format
Bearer <partner_api_key>
country query · string
ISO 3166-1 alpha-2 country code (case-insensitive). Returns only the plans offered in that country, that is plans linked to it plus plans linked to no country at all (offered everywhere). An unknown code answers `422`.
active query · boolean
`true` for plans on sale only, `false` for inactive plans only. Omit for both.
search query · string
Case-insensitive text matched against the plan's name and description. At most 100 characters.
per_page query · integer
Number of items per page, 1 to 5000. Defaults to `100`. A value above 5000 is rejected with `422`.
page query · integer
Page number to fetch, starting at 1. Defaults to `1`.
accept header · string
example: application/json

Responses

Response schema
dataarray<object>
Each item — A plan the partner that owns the API key may see: its own plans and the global Voxbi plans. Plans of other partners are never returned. A plan is offered in the countries listed in `countries`; an empty list means it is offered in every country (every plan created before countries existed behaves this way). Money values are decimal strings, never floats.
idstring · uuid
Unique identifier of the plan.
example: 550e8400-e29b-41d4-a716-446655440201
namestring
Plan name. Unique per country within your organization, case-insensitive.
example: Business
descriptionstring | null
Short description shown to customers.
example: For growing teams
price_per_userstring
Monthly price per user, as a decimal string.
example: 9.9000
currencystring
ISO 4217 currency code.
example: EUR
yearly_discountstring
Discount in percent when billed yearly, as a decimal string.
example: 10.00
price_overriddenboolean
For a plan linked to an Odoo product, whether your own price is kept when Odoo syncs. When false the price follows Odoo and cannot be changed through the API.
example:
max_usersinteger | null
Users included. Null means unlimited.
example: 25
max_numbersinteger | null
Phone numbers included. Null means unlimited, zero means none.
example: 10
numbers_are_fixedboolean
True when `max_numbers` is an exact count rather than a ceiling.
example:
ai_enabledboolean
Recording and AI features included.
example: 1
stats_enabledboolean
Statistics included.
example: 1
tempus_enabledboolean
Tempus time tracking included.
example:
featuresstring | null
Feature lines as stored, one per line.
example: Unlimited extensions Call recording
features_listarray<string>
The same feature lines, split and trimmed, empty lines dropped. Read only.
[]string
is_free_trial_allowedboolean
Whether a signup can start a free trial on this plan.
example: 1
free_trial_daysinteger
Length of the free trial in days.
example: 14
card_verification_requiredboolean
Customers must verify a payment card.
example:
card_deadline_daysinteger
Days to verify the card.
example: 0
card_reminder_days_beforeinteger
Days before the card deadline a reminder is sent.
example: 0
kyc_requiredboolean
Customers must complete KYC verification. Cannot be false on a plan that includes phone numbers.
example: 1
kyc_deadline_daysinteger
Days to complete KYC.
example: 7
kyc_reminder_days_beforeinteger
Days before the KYC deadline a reminder is sent.
example: 2
after_deadline_actionstring
What happens when a compliance deadline passes.
enum: block_services downgrade stay
example: stay
downgrade_to_plan_idstring | null · uuid
The plan customers are moved to when the action is `downgrade`.
downgrade_ceremony_daysinteger | null
Notice period in days before a downgrade.
example: 3
transfer_partner_idstring | null · uuid
The reseller a customer is handed to when its trial ends on this plan. Null when unset.
transfer_partner_namestring | null
Name of `transfer_partner_id`.
transfer_plan_idstring | null · uuid
The plan the customer gets at the target reseller. Null when unset (the customer moves without a plan).
transfer_plan_namestring | null
Name of `transfer_plan_id`.
is_activeboolean
Whether the plan is on sale. Customers already on an inactive plan keep it.
example: 1
sort_orderinteger
Display order, ascending.
example: 0
countriesarray<string>
ISO 3166-1 alpha-2 codes of the countries the plan is offered in, sorted. Empty means every country.
[]string
length: 2–2
signup_urlstring · uri
The public signup link that starts a trial on this plan, to publish on your website.
example: https://cockpit.voxbi.com/acme/signup/550e8400-e29b-41d4-a716-446655440201
customers_countinteger | null
How many of YOUR customers are on the plan now. Never counts another partner's customers on a global plan.
example: 4
sourcestring
Where the plan comes from, `manual` or `odoo`.
example: manual
is_globalboolean
True for a Voxbi plan offered to every partner. Global plans are read only.
example:
editableboolean
Whether your key's partner may change or delete the plan.
example: 1
created_atstring · date-time
example: 2026-10-01T08:00:00+00:00
updated_atstring · date-time
example: 2026-10-29T14:05:00+00:00
linksobject
firststring
The first page of the resource
example: http://localhost/api/v1/resources?page=1
laststring
The last page of the resource
example: http://localhost/api/v1/resources?page=1
prevnull | string
The previous page of the resource
nextnull | string
The next page of the resource
metaobject
current_pageinteger
The current page of the resource
≥ 1
example: 1
fromnull | integer
The first item of the resource
≥ 1
example: 1
last_pageinteger
The last page of the resource
≥ 1
example: 1
linksarray<object>
urlstring | null
The url of the resource (null for the boundary prev/next links)
example: http://localhost/api/v1/resources?page=1
labelstring
The label of the resource
example: first
activeboolean
The status of the resource
example: 1
pathstring
The path of the resource
example: http://localhost/api/v1/resources
per_pageinteger
The number of items per page of the resource
≥ 1
example: 15
tonull | integer
The last item of the resource
≥ 1
example: 1
totalinteger
The total number of items of the resource
≥ 0
example: 1
Unauthenticated. The `Authorization: Bearer <token>` header was missing, malformed, or names a token that has been revoked or deleted.
Response schema
messagestring
Forbidden. Three different situations share this status, told apart by `message`: * the token is not a partner API key (a user token, a PBX API key, or any other token); * the partner is not an active reseller; * the key lacks a scope the endpoint needs. The body then also lists `required_scopes`.
Response schema
messagestring
Human-readable reason.
example: This API key is missing a required scope.
required_scopesarray<string>
Present on the missing-scope 403 only. Scopes the endpoint needs that the key lacks.
[]string
Unprocessable Content. A query parameter or the body failed validation (`errors` keyed by field). Plans are unique per country: reusing a name in a country where you already sell a plan of that name fails on `name` and names the clashing countries. Nothing was changed.
Response schema
messagestring
The first validation error.
errorsobject
Validation errors keyed by field.
Free-form object
Too Many Requests. Two budgets apply: 120 requests per minute per API key, and 600 per minute across all of a partner's keys together. Wait for the number of seconds in the `Retry-After` header before retrying.
Response schema
messagestring
get https://cockpit.voxbi.com/api/v1/api/v1/plans
Base URL
Request sample
curl -X GET 'https://cockpit.voxbi.com/api/v1/api/v1/plans' \
  -H 'Authorization: Bearer YOUR_TOKEN'
const response = await fetch('https://cockpit.voxbi.com/api/v1/api/v1/plans', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${YOUR_TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
import requests

response = requests.get('https://cockpit.voxbi.com/api/v1/api/v1/plans',
    headers={'Authorization': f'Bearer {YOUR_TOKEN}'}
)
response.raise_for_status()
data = response.json()
print(data)
<?php
$context = stream_context_create([
    'http' => [
        'method'  => 'GET',
        'header'  => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_TOKEN",
    ],
]);

$response = file_get_contents('https://cockpit.voxbi.com/api/v1/api/v1/plans', false, $context);
$data = json_decode($response, true);
print_r($data);
{ … }
"data": [ … ],
{ … },
"id": "550e8400-e29b-41d4-a716-446655440201",
"name": "Business",
"description": "For growing teams",
"price_per_user": "9.9000",
"currency": "EUR",
"yearly_discount": "10.00",
"price_overridden": false,
"max_users": 25,
"max_numbers": 10,
"numbers_are_fixed": false,
"ai_enabled": true,
"stats_enabled": true,
"tempus_enabled": false,
"features": "Unlimited extensions Call recording",
"features_list": [ … ],
"Unlimited extensions",
"Call recording"
],
"is_free_trial_allowed": true,
"free_trial_days": 14,
"card_verification_required": false,
"card_deadline_days": 0,
"card_reminder_days_before": 0,
"kyc_required": true,
"kyc_deadline_days": 7,
"kyc_reminder_days_before": 2,
"after_deadline_action": "stay",
"downgrade_to_plan_id": null,
"downgrade_ceremony_days": 3,
"transfer_partner_id": null,
"transfer_partner_name": null,
"transfer_plan_id": null,
"transfer_plan_name": null,
"is_active": true,
"sort_order": 0,
"countries": [ … ],
"AT",
"LU"
],
"signup_url": "https://cockpit.voxbi.com/acme/signup/550e8400-e29b-41d4-a716-446655440201",
"customers_count": 4,
"source": "manual",
"is_global": false,
"editable": true,
"created_at": "2026-10-01T08:00:00+00:00",
"updated_at": "2026-10-29T14:05:00+00:00"
},
{ … },
"id": "550e8400-e29b-41d4-a716-446655440202",
"name": "Starter",
"description": "For growing teams",
"price_per_user": "4.9000",
"currency": "EUR",
"yearly_discount": "10.00",
"price_overridden": false,
"max_users": 5,
"max_numbers": 10,
"numbers_are_fixed": false,
"ai_enabled": false,
"stats_enabled": true,
"tempus_enabled": false,
"features": "Unlimited extensions Call recording",
"features_list": [ … ],
"Unlimited extensions",
"Call recording"
],
"is_free_trial_allowed": true,
"free_trial_days": 14,
"card_verification_required": false,
"card_deadline_days": 0,
"card_reminder_days_before": 0,
"kyc_required": true,
"kyc_deadline_days": 7,
"kyc_reminder_days_before": 2,
"after_deadline_action": "stay",
"downgrade_to_plan_id": null,
"downgrade_ceremony_days": 3,
"transfer_partner_id": null,
"transfer_partner_name": null,
"transfer_plan_id": null,
"transfer_plan_name": null,
"is_active": true,
"sort_order": 0,
"countries": [ … ],
"LU"
],
"signup_url": "https://cockpit.voxbi.com/acme/signup/550e8400-e29b-41d4-a716-446655440202",
"customers_count": 0,
"source": "manual",
"is_global": false,
"editable": true,
"created_at": "2026-10-01T08:00:00+00:00",
"updated_at": "2026-10-29T14:05:00+00:00"
},
{ … }
"id": "550e8400-e29b-41d4-a716-446655440203",
"name": "Voxbi Free",
"description": null,
"price_per_user": "0.0000",
"currency": "EUR",
"yearly_discount": "10.00",
"price_overridden": false,
"max_users": 25,
"max_numbers": 10,
"numbers_are_fixed": false,
"ai_enabled": true,
"stats_enabled": true,
"tempus_enabled": false,
"features": null,
"features_list": [],
"is_free_trial_allowed": true,
"free_trial_days": 14,
"card_verification_required": false,
"card_deadline_days": 0,
"card_reminder_days_before": 0,
"kyc_required": true,
"kyc_deadline_days": 7,
"kyc_reminder_days_before": 2,
"after_deadline_action": "stay",
"downgrade_to_plan_id": null,
"downgrade_ceremony_days": 3,
"transfer_partner_id": null,
"transfer_partner_name": null,
"transfer_plan_id": null,
"transfer_plan_name": null,
"is_active": true,
"sort_order": 0,
"countries": [],
"signup_url": "https://cockpit.voxbi.com/acme/signup/550e8400-e29b-41d4-a716-446655440201",
"customers_count": 1,
"source": "odoo",
"is_global": true,
"editable": false,
"created_at": "2026-10-01T08:00:00+00:00",
"updated_at": "2026-10-29T14:05:00+00:00"
}
],
"links": { … },
"first": "https://partner.voxbi.com/api/v1/plans?page=1",
"last": "https://partner.voxbi.com/api/v1/plans?page=1",
"prev": null,
"next": null
},
"meta": { … }
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [ … ],
{ … },
"url": null,
"label": "&laquo; Previous",
"active": false
},
{ … },
"url": "https://partner.voxbi.com/api/v1/plans?page=1",
"label": "1",
"active": true
},
{ … }
"url": null,
"label": "Next &raquo;",
"active": false
}
],
"path": "https://partner.voxbi.com/api/v1/plans",
"per_page": 100,
"to": 3,
"total": 3
}
}
{ … }
"message": "Unauthenticated."
}
Content-Type string
example: application/json
{ … }
"message": "This endpoint requires a partner API key."
}
Content-Type string
example: application/json
{ … }
"message": "You already have a plan with this name in Luxembourg. Plans are unique per country: choose a different name or different countries.",
"errors": { … }
"name": [ … ]
"You already have a plan with this name in Luxembourg. Plans are unique per country: choose a different name or different countries."
]
}
}
Content-Type string
example: application/json
{ … }
"message": "Too Many Attempts."
}
Retry-After integer
Seconds to wait before retrying.
example: 30
Content-Type string
example: application/json