Skip to content
Console
Browse documentation
Reference

Creating project-bound saved resources

Project selection, ownership checks, and retry behavior for custom dashboards and feature flags.

On this page

Custom dashboards and feature flags belong to a project, not just an organization. A project ID must identify an existing, active project in the authenticated organization. A correctly formatted UUID alone is not enough.

This applies to creating custom dashboards, cloning custom dashboards, and creating feature flags. A clone keeps its source dashboard's project and checks that project again.

Feature flag creation (POST /api/v1/flags, MCP create_flag, and CLI flags create) requires a project ID in its standard lower-case, hyphenated UUID form. Organization-wide credentials must supply project_id in the creation body. With a project-bound credential, its signed project is used even when the body omits project_id or names another value. That signed project is checked again for ownership and activation on every create. Creation requires flags:write; it does not additionally require projects:read. A rejected create stores no flag. A successfully created active flag is available to the same project's flag list, lookup, and evaluation.

Project selection and permissions

Organization-wide credentials must explicitly select a project when creating a dashboard. Dashboard creation requires project_id explicitly, and it must match a project-bound credential. Conflicting project selections are rejected. With a project-bound credential, repeat the exact signed project value; another UUID spelling still counts as a conflicting selection. Accepted organization-wide UUIDs are stored in their standard lower-case, hyphenated form, and equivalent UUID spellings use the same project identity for an idempotent retry. See the REST API reference for the route-specific selection and error contracts.

Dashboard creation and copying still require dashboard:write and an authenticated owning user. They do not additionally require projects:read. Existing owner, visibility, version, and idempotency rules still apply. Cloning saved-insight widgets also retains those widgets' existing access checks.

For API keys, the REST and MCP dashboard-clone routes require a key bound to the source dashboard's project; those routes refuse organization-wide API keys. The organization-wide project selection described above applies to dashboard creation.

Rejections and retries

An unknown project, a deleted project, an inactive project, and a project owned by another organization produce the same project-not-found response: HTTP 404. The response does not reveal which of those conditions applies, and no saved resource is created by the rejected request.

When current project ownership cannot be verified because a dependency is unavailable, creation fails rather than accepting an unchecked project. An outage normally returns HTTP 503; a deadline returns 504. Missing service configuration returns HTTP 400 and needs an operator correction, not a different project ID. These are not successful creations.

An idempotency key does not bypass project validation. Every retry checks the project's current state before it can create or replay a result. A project that became inactive or was deleted after an earlier request is not accepted merely because that earlier request succeeded.

These checks do not change the existing read, update, or delete permissions for saved resources. They do not move, relabel, or automatically delete older records that were created with an invalid project binding.

MCP project arguments follow the same rule for required-project reads and writes: a bound credential supplies its project, including instrumentation_doctor, and an organization credential supplies an explicit argument. Discovery marks the argument optional so bound credentials can omit it. A contradictory project is refused before the operation.