Promotions API
How promotions work: Promotions. The CLI equivalent is dtvsol promo ….
Authentication and errors: see the API overview.
GET /promotions
Section titled “GET /promotions”Every promotion (on now or not) and every plan’s speed now — or at another time with at.
| Name | In | Type | Notes |
|---|---|---|---|
at |
query | string | YYYY-MM-DD HH:MM (router’s local time): the speeds then, as a preview. |
curl -s "http://ROUTER-IP:8880/promotions" -H "X-API-Key: YOUR_API_KEY"{ "ok": true, "at": "2026-10-03 sat 23:30", "preview": false, "promotions": [ {"name": "nights", "enabled": true, "down": 3.0, "up": 1.0, "max_mbps": 1000, "days": [], "from": "22:00", "to": "06:00", "start": null, "end": null, "plans": [], "comment": "", "active": true, "words": "×3 down ×1 up, up to 1000 Mb/s, every day, 22:00–06:00, all plans"} ], "plans": { "plan_100_100": {"down_mbps": 300, "up_mbps": 100, "base_down_mbps": 100, "base_up_mbps": 100, "promotions": ["nights"]} }, "applied": {"speeds": {"plan_100_100": [300, 100]}, "at": "2026-10-03 23:30:00", "router_shaped": 12}}POST /promotions
Section titled “POST /promotions”Adds a promotion, or changes the one of that name (only the fields given change).
| Name | In | Type | Notes |
|---|---|---|---|
name |
body | string | 1–40 letters, digits, -, _. Required. |
down, up |
body | number | Multipliers from 1 to 10 (1 = unchanged). At least one above 1. |
max_mbps |
body | integer | The ceiling in Mbit/s; 0 or null = none. |
days |
body | array or string | sun mon tue wed thu fri sat; empty or all = every day. |
from, to |
body | string | HH:MM, both or neither (neither = the whole day). |
start, end |
body | string | YYYY-MM-DD, the first and last day. |
plans |
body | array or string | Plan names; empty = every plan. |
enabled |
body | boolean | Default true; false keeps it without running it. |
comment |
body | string | Up to 120 characters. |
curl -s -X POST "http://ROUTER-IP:8880/promotions" -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "saturday", "down": 2, "up": 2, "days": ["sat"]}'{"ok": true, "message": "promotion saturday: ×2, sat, all plans", "promotion": {…}, "active": false, "applied": {"changed": false}}; 400 for a value that is not valid, 404 for an unknown plan.
DELETE /promotions/{name}
Section titled “DELETE /promotions/{name}”Deletes a promotion; the speeds go back at once. 404 when there is none of that name.
GET /plan-tables
Section titled “GET /plan-tables”Every service on each registered OLT, and whether its service-port is on its plan’s own traffic tables (which a promotion can raise for that plan alone).
| Name | In | Type | Notes |
|---|---|---|---|
olt |
query | string | Only this OLT. |
{ "ok": true, "olts": { "olt-1": { "shared": 1, "services": [ {"id": "svc_1a2b3c4d", "name": "…", "plan": "plan_100_100", "pon": "0/1/3", "ont_id": 5, "download_table": "dtvsol-r107520", "upload_table": "dtvsol-r107520", "own_tables": false} ] } }}POST /plan-tables/move
Section titled “POST /plan-tables/move”Runs plan-sync on the OLT, then moves every service still on a shared table to its plan’s own tables, one after the other.
| Name | In | Type | Notes |
|---|---|---|---|
olt |
body | string | The OLT. Required. |
confirm |
body | boolean | Without it, only the list of what would be moved (dry_run: true, would_move). |
{"ok": true, "moved": ["svc_…"], "failed": []}; 502 with the services that failed.
POST /promotions/{name}
Section titled “POST /promotions/{name}”The same as POST /promotions with the name in the path; with {"delete": true} it deletes the
promotion, as DELETE /promotions/{name} does.
This site was written with the help of AI and checked by our team.