Static Talkgroups API β quick start
- Connect the hotspot to TGIF using its normal TGIF Hotspot Security Key.
- Create a device-scoped token from Static TG API Tokens.
- Create the token for the exact DMR ID / ESSID used by the hotspot on TGIF.
- Pi-Star: go to Admin β Expert β API Keys, paste the token into TGIF Static Talkgroups API Key β apikey, and select Apply Changes. Return to the Admin dashboard to use the TGIF Static TG Manager.
- Other clients / developers: store the token in the clientβs dedicated TGIF Static Talkgroups API token setting.
- Send HTTPS requests to
https://api.tgif.network/v1/static-talkgroups/{device}.
- Read once at startup or on manual refresh; write only when configuration changes.
curl -sS \
-H "Authorization: Bearer <YOUR_STATIC_TG_API_TOKEN>" \
https://api.tgif.network/v1/static-talkgroups/123456701
Replace 123456701 with the exact hotspot/repeater DMR ID presented to TGIF. Never publish or log the bearer token.
Authentication and device scope
Bearer token
Every request uses an HTTP Authorization header:
Authorization: Bearer <YOUR_STATIC_TG_API_TOKEN>
The full secret is shown only once when the token is created. TGIF stores only a cryptographic hash of the secret.
Runtime authorization
A valid token is not enough by itself. TGIF also verifies that the requested device matches the token, is currently connected, belongs to the token account and is using TGIF secure hotspot authentication.
A token created for one ESSID cannot control another ESSID. A token for 123456701 cannot be used against 123456702.
Endpoint and data model
https://api.tgif.network/v1/static-talkgroups/{device_dmr_id}
{device_dmr_id} must contain 6 to 9 decimal digits. Static memberships are represented as a timeslot and talkgroup pair.
{"slot":2,"talkgroup":31665}
Talkgroup values must be between 1 and 16,777,215 and must not be a TGIF reserved/special destination. TG 9, 777, 4000, 9990 and 31000 are protected.
HTTP methods
| Method | Purpose | Request body |
GET | Read current Static TG state and supported timeslots. | None |
POST | Add one membership. Duplicate adds are idempotent. | {"slot":2,"talkgroup":31665} |
DELETE | Remove one membership. Removing an absent membership is idempotent. | {"slot":2,"talkgroup":31665} |
PUT | Replace the complete membership set atomically. | {"memberships":[...]} |
OPTIONS | Return the allowed methods. | None |
Read state
curl -sS \
-H "Accept: application/json" \
-H "Authorization: Bearer <YOUR_STATIC_TG_API_TOKEN>" \
https://api.tgif.network/v1/static-talkgroups/123456701
Add TG 31665 on TS2
curl -sS -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_STATIC_TG_API_TOKEN>" \
--data '{"slot":2,"talkgroup":31665}' \
https://api.tgif.network/v1/static-talkgroups/123456701
Delete TG 31665 on TS2
curl -sS -X DELETE \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_STATIC_TG_API_TOKEN>" \
--data '{"slot":2,"talkgroup":31665}' \
https://api.tgif.network/v1/static-talkgroups/123456701
Replace the complete set
curl -sS -X PUT \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_STATIC_TG_API_TOKEN>" \
--data '{"memberships":[{"slot":2,"talkgroup":31665}]}' \
https://api.tgif.network/v1/static-talkgroups/123456701
Write bodies must use Content-Type: application/json and are limited to 4096 bytes.
Response examples
GET success
{
"ok": true,
"device": 123456701,
"enabled": true,
"limit": 5,
"supports_ts1": false,
"supports_ts2": true,
"memberships": [
{"slot": 2, "talkgroup": 31665}
],
"request_id": "..."
}
The limit value is the maximum number of Static TG memberships allowed per supported timeslot for that hotspot. With a limit of 5, a two-slot hotspot may therefore hold up to 5 on TS1 and 5 on TS2.
Pi-Star / MMDVM timeslots: a simplex or single-timeslot hotspot uses TS2 only for Static Talkgroups. A true duplex/repeater-style MMDVM device may expose TS1 and TS2 when the live TGIF session reports both slots as supported. Clients must follow supports_ts1 and supports_ts2; do not infer Static TG capability from the legacy Pi-Star dynamic manager controls.
Mutation success
{
"ok": true,
"device": 123456701,
"changed": true,
"runtime_seen": true,
"memberships": [
{"slot": 2, "talkgroup": 31665}
],
"request_id": "..."
}
changed:false means the requested state already existed, so no membership write or CallMGR reload was required. runtime_seen:true means a live CallMGR subscriber saw the reload notification.
HTTP status and error handling
| HTTP | Meaning | Client action |
| 400 | Invalid device, JSON or request structure. | Fix the request; do not retry unchanged input. |
| 401 | Missing, malformed, revoked or invalid API credential. | Check or recreate the credential. |
| 403 | Account/device ownership, secure-hotspot or policy authorization failed. | Check device scope and TGIF secure connection. |
| 409 | Device offline, Static TG disabled or concurrent update conflict. | Refresh state later; do not spin. |
| 413 | Request body too large. | Reduce the request. |
| 415 | Write request is not application/json. | Send the correct Content-Type. |
| 422 | Unsupported slot, reserved/invalid TG, duplicate entry or membership limit. | Correct the requested configuration. |
| 426 | HTTPS is required. | Use the HTTPS API URL. |
| 429 | Rate limited at the HTTP edge. | Stop and retry later with backoff/jitter. |
| 503 | Backing-store/runtime state could not be safely read or written. | Back off and retry later. |
JSON errors contain ok:false, an error code and a request_id for support correlation.
Required client behaviour
Continuous polling is not supported. The API is an event-driven configuration interface, not a live telemetry feed.
- Perform one GET when the client starts or its configuration UI opens.
- Cache the returned state locally.
- Send POST, DELETE or PUT only when the user changes configuration.
- Allow an explicit manual refresh to perform another GET.
- On network failure, 429 or 503, use delayed exponential backoff with random jitter if an automatic retry is necessary.
Do not use a synchronized fixed retry timer, daemon loop or short polling interval.
Dashboard integration pattern
This section is for developers adding TGIF Static Talkgroup controls to another hotspot dashboard.
- Use the exact DMR ID / ESSID that the hotspot presents to TGIF.
- Provide a separate Static TG API Token setting in the dashboard.
- Keep the saved credential on the hotspot side and do not expose it in page output or logs.
- Perform one GET when the Static TG panel opens and follow supports_ts1, supports_ts2 and limit from the response.
- Use POST to add a membership, DELETE to remove one, and PUT only to replace the complete set.
- After a successful change, refresh the displayed state once. Do not run a polling loop.
Timeslots: simplex hotspots normally use TS2. Duplex devices may support TS1 and TS2. Always follow the capability fields returned by TGIF.
Network behaviour: use HTTPS with certificate and hostname verification. For 429, 503 or transient failures, back off rather than repeatedly retrying.
Pi-Star reference: install the credential at Admin β Expert β API Keys β TGIF Static Talkgroups API Key β apikey β Apply Changes. Pi-Star then reads state for that hotspot and exposes the TGIF Static TG Manager on the Admin dashboard. Other clients should follow the same credential-handling model without exposing the token in page output or logs.