# Secrets Store credentials once, reference them from any component, and understand what has to be unhooked before a secret can be deleted. ## Overview A secret is an org-scoped named credential. Components never hold credential values inline — they hold a reference to a secret, and Monad resolves it at run time. Two things to know: - **Values are write-only.** The API returns secret metadata — name, description, timestamps, and the resources that reference it — but never the value. Reading a secret back is not possible, so keep your own copy in a secrets manager if you will need it again. - **A referenced secret cannot be deleted.** Deletion is refused while anything still points at the secret, and "referenced" is broader than you might expect. See [Deleting a secret](#deleting-a-secret). ### Required Permissions | Permission | Description | |---|---| | `secrets:read` | List and view secret metadata | | `secrets:write` | Create and update secrets | | `secrets:delete` | Delete secrets that are no longer referenced | For details on assigning these permissions, see the [Organization RBAC guide](/guides/organization-rbac). ## Creating a Secret 1. Navigate to your organization and select the **Secrets** tab. 2. Create the secret, giving it a name and its value. 3. Reference it from a component — input, output, enrichment, or transform — by selecting it in the component's credential field. Via the API, create a secret with [`POST /v2/{organization_id}/secrets`](/api/secrets#create-secret). Authenticate with an [API key](/guides/api-keys) in the `x-api-key` header: ```bash curl -X POST https://app.monad.com/api/v2/{organization_id}/secrets \ -H "x-api-key: $MONAD_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "splunk-hec-token", "description": "HEC token for the security index", "value": "00000000-0000-0000-0000-000000000000" }' ``` A `201` returns the secret's metadata. Note that the value is not echoed back: ```json { "id": "3f1c9e64-8a12-4c7d-9f30-1b2c4d5e6f70", "organization_id": "9b21338e-73ef-4cc3-bcde-c8b5adaa5125", "name": "splunk-hec-token", "description": "HEC token for the security index", "created_at": "2026-08-05T22:31:04Z", "updated_at": "2026-08-05T22:31:04Z" } ``` Use that `id` wherever a component's configuration expects a secret reference. ## Sharing a Secret A top-level organization can share a secret with its teams, so a team can use a credential you manage without ever seeing its value. Secrets are one of five shareable resource types; the [Resource Sharing guide](/guides/resource-sharing) covers the full flow. What is specific to secrets: - **The value stays hidden.** A shared secret appears in the receiving team's secret selectors with a **Shared with team** badge. The team can reference it from its components, but cannot view its value, edit it, or delete it. - **Rotation propagates.** Update the value once in the owning organization and every team's components pick up the new value, with no coordination required. - **Teams cannot re-share.** A secret shared *with* your organization cannot be shared onward. - **Unsharing is blocked while the team is using it.** Remove the team's use of the secret first; see [Unsharing and resources in use](/guides/resource-sharing#unsharing-and-resources-in-use). ## What Counts as "In Use" A secret is in use when **anything references it**, whether or not that thing is running. Five kinds of reference exist: | Reference | Example | |---|---| | Input | an API token on a connector that pulls data | | Output | a bot token on a Slack destination | | Enrichment | an API key on a lookup provider | | Transform | HMAC key material on a `mask` operation | | Pipeline node override | a credential set on a single node of one pipeline, overriding the component's own configuration | Two consequences worth internalizing: - **A disabled pipeline still counts.** So does a component that belongs to no pipeline at all. If a component exists and names the secret, the secret is in use. - **"Not currently receiving data" is not the same as "unused."** An idle connector holds its reference exactly like a busy one. ## Finding What References a Secret Before deleting, check what points at it with [`GET /v2/{organization_id}/secrets/{secret_id}`](/api/secrets#get-secret-with-components): ```bash curl -H "x-api-key: $MONAD_API_KEY" \ https://app.monad.com/api/v2/{organization_id}/secrets/{secret_id} ``` The response lists the `inputs`, `outputs`, `enrichments`, and `transforms` that reference the secret: ```json { "id": "3f1c9e64-8a12-4c7d-9f30-1b2c4d5e6f70", "name": "splunk-hec-token", "inputs": [], "outputs": [{ "id": "7c4e...", "name": "Splunk HEC" }], "enrichments": [], "transforms": [{ "id": "b91a...", "name": "Mask employee identity" }] } ``` [`GET /v2/{organization_id}/secrets`](/api/secrets#list-secrets-with-components) returns the same lists for every secret in the organization, which is the efficient way to audit a whole organization at once: ```bash curl -H "x-api-key: $MONAD_API_KEY" \ "https://app.monad.com/api/v2/{organization_id}/secrets?limit=100&offset=0" ``` Two cautions when auditing: - **These lists do not include pipeline-node overrides.** A secret referenced only by a node override shows four empty lists here and still cannot be deleted. The deletion error names the pipeline, so you are not left guessing — but an empty pre-check is not a guarantee. - **Paginate.** List endpoints return a limited page by default, so pass `limit` and `offset` and read to the end. Auditing "which secrets are unused?" from a single unpaginated page will report in-use credentials as unused. ## Deleting a Secret Delete with [`DELETE /v2/{organization_id}/secrets/{secret_id}`](/api/secrets#delete-secret): ```bash curl -X DELETE -H "x-api-key: $MONAD_API_KEY" \ https://app.monad.com/api/v2/{organization_id}/secrets/{secret_id} ``` | Response | Meaning | |---|---| | `204` | Deleted. | | `409` | Still referenced. The message names every referencing resource. | | `403` | The secret was shared with your organization by another organization; only its owner can delete it. | | `404` | No such secret in this organization. | A `409` looks like this: ```json { "code": 409, "error": "Secret cannot be deleted because it is in use by: Outputs: Splunk HEC (type: splunk); Transforms: Mask employee identity" } ``` To proceed, edit each named resource to stop referencing the secret — point it at a different secret or clear the field — then delete the secret. Deleting the *component* also releases its reference. If the secret is shared with other organizations, remove the shares first — see [Sharing a secret](#sharing-a-secret). ## Rotating a Secret Update the secret's value in place rather than creating a replacement, so every component that references it picks up the new value without reconfiguration. In the UI, edit the secret and save a new value; via the API, use [`PATCH /v2/{organization_id}/secrets/{secret_id}`](/api/secrets#update-secret): ```bash curl -X PATCH https://app.monad.com/api/v2/{organization_id}/secrets/{secret_id} \ -H "x-api-key: $MONAD_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "value": "the-new-value" }' ``` A `200` returns the secret's metadata, with `updated_at` advanced. Sending only `value` leaves the name and description unchanged. One caveat specific to deterministic operations: the `mask` transform's deterministic mode derives its output from the key material, so rotating that secret changes every future digest. Values masked before the rotation will no longer match values masked after it. Treat a key used for deterministic masking as long-lived.