The Storefront API lets you retrieve and update your pricing configuration programmatically — TLD pricing, add-on pricing, currencies, default markup, price rounding, and tax rules — without logging into Storefront Manager. This is useful for feeding pricing data into your own billing or reporting systems, or managing your pricing configuration from your own tooling.
Before you begin
Requirements
- An active OpenSRS Storefront with API access enabled
- API credentials (Client ID and Client Secret) — see API DNS Management Guide for how to generate these and obtain an access token. Pricing uses the same OAuth 2.0 Client Credentials flow, the same base URLs, and the same 600 requests/minute rate limit as DNS — no separate setup needed.
- Your OpenSRS account balance above $10 to keep your Storefront active
The login ID header
Most endpoints below accept an optional x-osrs-system-login-id header — the ID of the specific login to act as, needed only if your reseller account has more than one login to choose from. If you only have one, you can omit it.
curl -X GET "https://api.shopco.com/v1/tlds" \ -H "Authorization: Bearer <access_token>" \ -H "x-osrs-system-login-id: <login_id>"
TLD endpoints
List your TLD catalogue
Returns every TLD available to you, with its current pricing configuration — not just TLDs you've enabled.
GET /v1/tlds
Example cURL
curl -X GET "https://api.shopco.com/v1/tlds" \ -H "Authorization: Bearer <access_token>"
Example response
200 OK — an array of TLD entries.
[ { "name": "com", "true_tld": "com", "status": "custom_pricing", "markup": 20, "retail_price": 14.99, "osrs_price": 9.99, "currency_code": "USD", "currency_symbol": "$" } ]
| Field | Description |
|---|---|
name | The TLD |
true_tld | Underlying TLD identifier |
status | Pricing status (e.g. custom_pricing) |
markup | Current markup percentage |
retail_price | What your customers are charged |
osrs_price | OpenSRS's underlying cost |
currency_code / currency_symbol | Currency this row is priced in |
Note: this endpoint doesn't currently support filtering by TLD type or pagination — it returns your full catalogue in one response.
Get pricing for a TLD
Returns the pricing strategy and cost basis for one TLD, broken out by operation.
GET /v1/tld/{tld}/pricing
Path parameters
| Parameter | Type | Description |
|---|---|---|
tld | string | The top-level domain, e.g. com |
Example cURL
curl -X GET "https://api.shopco.com/v1/tld/com/pricing" \ -H "Authorization: Bearer <access_token>"
Example response
200 OK
{ "registration": "custom_markup", "registration_custom_markup": 20, "registration_custom_final_price": null, "transfer": "same_as_registration", "transfer_custom_markup": null, "transfer_custom_final_price": null, "renew": "same_as_registration", "renew_custom_markup": null, "renew_custom_final_price": null, "redemption": "default", "redemption_custom_markup": null, "redemption_custom_final_price": null, "registration_osrs": 9.99, "transfer_osrs": 9.99, "renew_osrs": 9.99, "redemption_osrs": 79.99 }
Each operation — registration, transfer, renew, redemption — has its own pricing strategy:
| Strategy | Meaning |
|---|---|
default | Use your storefront's default markup |
custom_markup | A specific markup percentage for this TLD and operation (see <operation>_custom_markup) |
custom_final_price | A fixed price you set directly, in USD plus any other configured currencies (see <operation>_custom_final_price) |
same_as_registration | Transfer, renew, and redemption only — mirrors whatever registration is set to |
<operation>_osrs fields report OpenSRS's underlying cost for that operation, regardless of strategy.
Note: pricing here is per operation and per currency — there's no separate rate for different registration term lengths (1 year vs. multi-year).
Set pricing on TLDs
Applies one pricing configuration to one or more TLDs in a single request.
POST /v1/tlds/set_pricing
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
tlds | array of strings | Yes | TLDs to apply this pricing to |
registration | string | Yes | default, custom_markup, or custom_final_price |
registration_custom_markup | integer (0–999) | If registration is custom_markup | Percent |
registration_custom_final_price | object | If registration is custom_final_price | {"usd_price": <number>, "foreign_currency_prices": [{"currency_code": "CAD", "price": <number>}, ...]} |
transfer / renew / redemption | string | Yes / Yes / No | Same options as registration, plus same_as_registration |
transfer_custom_markup, renew_custom_markup, redemption_custom_markup | integer (0–999) | If that operation is custom_markup | Percent |
transfer_custom_final_price, renew_custom_final_price, redemption_custom_final_price | object | If that operation is custom_final_price | Same shape as above |
enable_tlds | boolean | No, default true | Also enable the given TLDs at the same time |
Note: this applies the same pricing to every TLD in the tlds array in one call — it doesn't accept different prices per TLD. To price TLDs differently, send separate requests.
Example request
{ "tlds": ["com", "net"], "registration": "custom_markup", "registration_custom_markup": 20, "transfer": "same_as_registration", "renew": "same_as_registration", "redemption": "default", "enable_tlds": true }
Example cURL
curl -X POST "https://api.shopco.com/v1/tlds/set_pricing" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{ "tlds": ["com", "net"], "registration": "custom_markup", "registration_custom_markup": 20, "transfer": "same_as_registration", "renew": "same_as_registration", "redemption": "default", "enable_tlds": true }'
Response: 200 OK
Enable or disable TLDs
Turns one or more TLDs on or off for your storefront in a single request.
POST /v1/tlds/set_enabled_status
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
tlds | array of strings | Yes | TLDs to update |
enabled | boolean | Yes | true to enable, false to disable |
Example cURL
curl -X POST "https://api.shopco.com/v1/tlds/set_enabled_status" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{ "tlds": ["org"], "enabled": true }'
Response: 200 OK
Get TLD status
Checks whether a single TLD is enabled on your storefront.
GET /v1/tld/{tld}/status
Example cURL
curl -X GET "https://api.shopco.com/v1/tld/org/status" \ -H "Authorization: Bearer <access_token>"
Example response
{ "enabled": true }
Add-on pricing
Covers contact (WHOIS) privacy pricing — currently the only add-on this API exposes.
Get add-on pricing
GET /v1/pricing/add_on
Example response
{ "contact_privacy": { "usd_price": 4.99, "foreign_currency_prices": [ { "currency_code": "CAD", "price": 6.49 } ] }, "contact_privacy_osrs": 1.50 }
Update add-on pricing
PUT /v1/pricing/add_on
Example request
{ "contact_privacy": { "usd_price": 4.99, "foreign_currency_prices": [ { "currency_code": "CAD", "price": 6.49 } ] } }
Response: 200 OK
Currencies
Get configured currencies
Returns every currency enabled on your storefront, as an exchange rate against USD.
GET /v1/currencies
Example response
[ { "code": "CAD", "descr": "Canadian Dollar", "symbol": "$", "is_default": false, "value_of_1_usd": 1.35, "active_customers": 214 } ]
| Field | Description |
|---|---|
code | ISO 4217 currency code |
descr | Human-readable name |
symbol | Currency symbol |
is_default | Whether this is your default currency |
value_of_1_usd | Exchange rate — units of this currency per 1 USD |
active_customers | Customers currently billed in this currency (via auto-renew domains or active subscriptions) |
Create or update a currency
There's no separate create call — this same endpoint creates a currency if the code doesn't exist yet, or updates it if it does.
PUT /v1/currency/{code}
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
is_default | boolean | Yes | Whether this becomes your default currency |
value_of_1_usd | number | Yes | Exchange rate — units of this currency per 1 USD |
Example cURL
curl -X PUT "https://api.shopco.com/v1/currency/CAD" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{ "is_default": false, "value_of_1_usd": 1.35 }'
Response: 200 OK
Delete a currency
DELETE /v1/currency/{code}
Example cURL
curl -X DELETE "https://api.shopco.com/v1/currency/CAD" \ -H "Authorization: Bearer <access_token>"
Response: 200 OK
Note: the spec doesn't document what happens if you delete your default currency, or one with active customers still billed in it — confirm the actual behavior before publishing.
Default markup
Get default markup
GET /v1/pricing/default_markup
Response: 200 OK — an integer percentage, e.g. 20.
Update default markup
PUT /v1/pricing/default_markup
Example cURL
curl -X PUT "https://api.shopco.com/v1/pricing/default_markup" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '20'
Valid range: 0–999. There's no separate "type" — the default markup is always a percentage.
Response: 200 OK
Price rounding
Get price rounding configuration
GET /v1/pricing/rounding
Response: 200 OK — one of rounding_off, rounding_to_dollar, or rounding_to_99.
Update price rounding configuration
PUT /v1/pricing/rounding
Example cURL
curl -X PUT "https://api.shopco.com/v1/pricing/rounding" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '"rounding_to_99"'
This is a single storefront-wide setting, not configurable per TLD or currency.
Response: 200 OK
Tax rules
Get all tax rules
GET /v1/tax_rules
Example response
[ { "id": "b3f1c2d4-5678-4abc-9def-0123456789ab", "name": "Ontario HST", "rate": 0.13, "country": "CA", "country_name": "Canada", "state_province": "ON", "tax_id": "HST-123456" } ]
An empty array is returned if you haven't configured any tax rules.
Get a tax rule
GET /v1/tax_rule/{tax_rule_id}
tax_rule_id is the UUID returned when the rule was created. Returns null if no rule matches.
Create a tax rule
POST /v1/tax_rule
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name, e.g. Ontario HST |
rate | number (0–1) | Yes | Tax rate as a fraction, e.g. 0.13 for 13% |
country | string | Yes | 2-letter ISO country code |
state_province | string or null | No | State/province this rule applies to; omit or send null for a country-wide rule |
tax_id | string or null | Yes | Your tax registration ID for this jurisdiction, if any |
Example cURL
curl -X POST "https://api.shopco.com/v1/tax_rule" \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{ "name": "Ontario HST", "rate": 0.13, "country": "CA", "state_province": "ON", "tax_id": "HST-123456" }'
Response: 200 OK
Update a tax rule
PUT /v1/tax_rule/{tax_rule_id}
Same request fields as create — this replaces the rule's fields, not a partial update.
Delete a tax rule
DELETE /v1/tax_rule/{tax_rule_id}
Deleting, updating, or retrieving a tax rule ID that doesn't exist returns an error.
Check tax ID usage
Groups your tax rules by their shared tax_id value and reports how many rules use each one — useful for checking whether a tax registration ID is already attached to other rules before changing or removing it.
GET /v1/tax_rule/tax_ids
Example response
[ { "name": "HST-123456", "used_by": 3 } ]
name here is the tax ID value itself (not a rule name); null represents rules with no tax ID set.
Error responses
Standard validation errors (422) follow FastAPI's usual shape:
{ "detail": [ { "type": "missing", "loc": ["body", "rate"], "msg": "Field required", "input": {} } ] }
Beyond what's called out per endpoint above, any endpoint in this guide can also return:
| Status | Meaning |
|---|---|
| 401 Unauthorized | Missing or invalid token |
| 403 Forbidden | Authenticated, but not authorized for this resource |
| 404 Not Found | Resource doesn't exist |
| 409 Conflict | Resource already exists (on create) |
| 422 Unprocessable Entity | Request failed validation |
| 429 Too Many Requests | Rate limit exceeded — check Retry-After header |
| 500 Internal Server Error | Unexpected failure — contact support, quoting the x-error-id response header |
Money values throughout this API are decimals (e.g. 2.33 for $2.33), not integer cents.
Related articles
- API: Managing Customers — create, read, and update customer accounts via API
- API DNS Management Guide — API credentials, authentication, and DNS record management
- Setting up your domain pricing — the UI-based equivalent for TLD pricing and markup
- Selling in multiple currencies — the UI-based equivalent for currency setup
- Collecting taxes — the UI-based equivalent for tax rules
Questions or issues with the API? Contact OpenSRS Support.
How helpful was this article?
Thanks for your feedback!
Do you still need help? If so please submit a request here.