v3
latestOpenAPI 3.1.02026-07-311,4541,5202.3 MBUser Invitations Organization User Roles List
Plug-and-play plan-level count-limit enforcement on resource creation.
A view declares ONE resource tag — its permission_resource (the same Resources value that drives the RBAC permission) — and this mixin hooks create() to enforce that resource's plan count limit automatically. No separate plan_limited_resource: the resource tag is the single source.
class DatasetsView(PlanLimitMixin, PermissionMapMixin, ListCreateAPIView):
permission_resource = Resources.DATASETS
# RBAC perm AND the dataset count cap both derive from this tag.
The "what" (model/field/filters/error per resource) lives in the utils.plan_limits registry; PLAN_LIMIT_BY_RESOURCE maps the resource tag → its GatedResource. A tag with no registry entry simply has no cap.
How the hook fires: DRF's ListCreateAPIView.post() delegates to self.create(), and views that override post() end with super().post() — both reach this mixin's create() (it sits before the generic view in the MRO). Views that define their own create() just need to call super().create() and honour its return value.
Org resolution: get_limit_organization() defaults to the view's get_organization() (the org the resource is created under, after any superadmin injection), falling back to the request user's org. Override it for bespoke resolution (e.g. a superadmin target org).
Custom non-create() handlers (e.g. an update_or_create upsert) can't be hooked; those call enforce_declared_limit() explicitly — still driven off the same resource tag.
Staff exemption: Respan staff acting on an org's behalf bypass ALL plan limits — a cross-cutting policy enforced centrally in enforce_declared_limit (see is_plan_limit_exempt), not re-stated per view. Every gated resource inherits it.
Query parameters
A page number within the paginated result set.
Number of results to return per page.
Headers
JWT access token or Respan API key