User Panel API — 2.4.2 → 2.5.0 (Integrator Migration Guide)
Previous Release: 2.4.2 · New Release: 2.5.0
Audience: external integrators with existing User Panel API integrations.
This guide covers only the changes that affect existing integrations, with before/after examples and migration steps. Please review each section before upgrading.
1. Summary — What Actually Affects You
In plain terms: four of these six items are security hardening — they only break access that shouldn't have worked in the first place (viewing or touching another team's data). If your integration only ever touches its own team's resources, those four change nothing for you. One item (region scoping) is the one to actually worry about: it doesn't error, it just quietly returns less data, so it can hide in production for a while before anyone notices. The deprecation is a heads-up, not a deadline — the old endpoint still works.
Change | Who is affected | Action | Practical impact | Why this was changed |
|---|---|---|---|---|
| Non-admin callers that omit | Pass an explicit scope, or expect a narrower list | 🔴 High — silent. Still | Part of the same team-data-isolation pass as the rows below — regions were the one list still handed out system-wide to non-admins with no membership check at all. |
| Clients that branch on | Handle | 🟡 Medium. Only affects clients that hard-code the old status code, or expect the record to be physically deleted rather than soft-deleted. | Hard-deleting a policy that a team is still on (or the default policy) would corrupt that team's active billing configuration and orphan historical invoices that reference it. Soft-delete keeps the record for historical billing while removing it from the active list; |
| Anyone relying on cross-team visibility (should not have had it) | Expect | 🟢 Low — security fix. Only breaks access to teams you weren't supposed to see (this was an IDOR bug). A well-behaved integration that only queries its own teams sees no change. | Closes an IDOR: the handler never checked membership, so any authenticated caller could pass any |
11 instance endpoints now check ownership | Anyone accessing instances outside their active team memberships | Expect | 🟢 Low — security fix. Same pattern: only breaks stale/cross-team access. Worth a check if a service account was recently removed from a team. | The underlying instance lookup was missing an active-membership filter, so a user removed from a team could still view or send power actions to that team's instances by ID. Same IDOR class as above, found on action/detail endpoints instead of list endpoints. |
Legacy | Same as above, on the legacy endpoint | Same as above | 🟢 Low — security fix. Same as above. | Same root cause as the row above (a membership JOIN missing an active-status filter) in a separate, older code path that wasn't caught in the same pass. |
| Anyone calling this endpoint | Migrate to | ⚪ None yet. Deprecated, not removed — the old endpoint still works this cycle. No urgency, just don't build anything new on it. |
|
There are no removed endpoints. 106 new endpoints were added (Token Factory, Advanced Networking, billing/metrics) — purely additive.
2. Breaking: Baremetal instance endpoints now enforce team membership
Before: GET /baremetal/instances without team_id returned every team's instances; supplying any team_id on GET /baremetal/instances or GET /baremetal/instances/{id} worked regardless of whether you belonged to that team, including SSH connection details.
After:
GET /baremetal/instances/{id} (id not in caller's teams) → 403 Forbidden GET /baremetal/instances (no team_id) → [] instead of every team's rows
Migration: always pass a team_id you belong to. Expect 403 on instance IDs outside your active team memberships.
3. Breaking: Region endpoints silently scoped to your team
GET /regions, GET /regions/sync, and GET /instance/available-regions keep the same signature — team_id is still optional — but a non-admin caller who omits it now gets only the regions available to their own active team memberships, not the full system-wide list.
Migration: if your integration expects every region regardless of team, that behavior is no longer guaranteed for non-admin credentials. This will not show up as an error — check whether your region list has gotten shorter after upgrading.
4. Breaking: Instance endpoints now check ownership
Affects: instance info, exposed-services, refresh-connections, resize options, datastores, storage-blocks, five pod-resize endpoints, and the legacy GET /api/instance.
Before: a user removed from a team could still view or send power actions to that team's instances by ID.
After: 403 Forbidden for any instance ID outside your active team memberships.
Migration: if a service account was removed from a team, expect it to lose access to that team's instances going forward — this is now enforced, not incidental.
5. Breaking: Pricing policy delete semantics changed
Before:
DELETE /pricing-policy/{id} → 200 OK, or 403 if it couldn't be deleted
After:
DELETE /pricing-policy/{id} → 200 OK (never assigned to a team — hard delete) → 200 OK (assigned in the past — soft delete, kept for historical billing) → 409 Conflict (currently assigned to a team, or is the default policy)
Migration: if you retry or branch on 403 for this endpoint, update that logic to handle 409 instead.
6. Deprecation: team policy assignment
PUT /policy/{policy_type}/assign-team is deprecated. Use:
PUT /policy/{policy_type}/update-teams
which replaces the team's full assignment set atomically in one call.
7. New Capabilities (informational, no migration required)
Token Factory — GPU model serving, fine-tuning, and RAG under
/team/{team_id}/tf/*, plus admin and public-API surfaces.Advanced Networking — private VLANs, subnets, and Elastic IPs under
/team/{team_id}/network/*.
Both are purely additive.