> For the complete documentation index, see [llms.txt](https://docs.contextual.io/documentation-and-resources/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.contextual.io/documentation-and-resources/components-and-data/object-types/object-type-details/data-schema/secret.md).

# Secrets

Set `"secret": true` on a String property in your Data Schema to store its value in an encrypted key store. Contextual replaces the value in the stored record with the literal string `<ENCRYPTED>` and keeps a reference to the secret.

Encrypted storage and the value returned to a caller are separate concerns. An authorized request can return a decrypted value, even when a Console form hides the field.

{% code title="Secret Property Definition" lineNumbers="true" %}

```json
{
  "mySecretProperty": {
    "description": "Values will be encrypted and stored as a secret",
    "type": "string",
    "secret": true
  }
}
```

{% endcode %}

## How Secrets are Returned and Revealed Using the Tenant API

### Single-record GET responses

For records stored in Contextual, a single-record `GET` requires **Read** permission on the Object Type. Secret decryption also depends on the caller's permissions on that Object Type and the `doNotDecrypt` query parameter:

| Permissions on the Object Type | GET without `doNotDecrypt=true` | GET with `doNotDecrypt=true` |
| ------------------------------ | ------------------------------- | ---------------------------- |
| Read                           | `<ENCRYPTED>`                   | `<ENCRYPTED>`                |
| Read and Create                | `<ENCRYPTED>`                   | `<ENCRYPTED>`                |
| Read and Reveal                | Decrypted value                 | `<ENCRYPTED>`                |
| Read and Update                | Decrypted value                 | `<ENCRYPTED>`                |

Create alone does not permit GET decryption. Reveal or Update permits decryption only when the caller also has Read permission to retrieve the record. These rules apply to record GETs by primary key and by secondary key.

Set `doNotDecrypt=true` when you need to retrieve a record without its secret values, including when inspecting records in scripts or AI-assisted workflows. This parameter controls decryption for that response; it does not change the stored secret or the caller's permissions.

For example, using the [Tenant API base URL](/documentation-and-resources/tenants/what-is-the-tenant-api.md), this request returns placeholders for stored secrets:

```http
GET /api/v1/example/example-001?doNotDecrypt=true
```

The following response excerpt uses synthetic data. `_metaData.secrets` lists the paths of the stored secret properties, such as `mySecretProperty` or a nested path like `credentials.0.value`.

{% code title="Record Response Excerpt with Decryption Disabled" lineNumbers="true" %}

```json
{
  "invoiceId": "example-001",
  "mySecretProperty": "<ENCRYPTED>",
  "_metaData": {
    "id": "example-001",
    "schema": "native-object:example",
    "type": "custom",
    "secrets": [
      "mySecretProperty"
    ]
  }
}
```

{% endcode %}

Without `doNotDecrypt=true`, a caller with Read and either Reveal or Update can receive `"mySecretProperty": "synthetic-example-secret"` in the same record response. The `<ENCRYPTED>` placeholder is therefore conditional, even though the secret remains encrypted in storage.

### Reveal an individual secret

To retrieve a specific secret explicitly, send a `POST` to `/$secrets/{typeId}/{recordId}` under the Tenant API base URL, with the property path in the request body. This endpoint has a separate permission check: it accepts **Create**, **Update**, or **Reveal** permission on the Object Type. The single-record GET permission rules above do not determine access to this endpoint.

```http
POST /api/v1/$secrets/example/example-001
Content-Type: application/json

{
  "path": "mySecretProperty"
}
```

{% code title="Synthetic Secret Response" lineNumbers="true" %}

```json
{
  "value": "synthetic-example-secret"
}
```

{% endcode %}

See your tenant's [API documentation](/documentation-and-resources/tenants/what-is-the-tenant-api/documentation.md) for its base URL and Object Type endpoints.

## Console presentation

Record forms initially conceal stored secret values. Use the eye icon or **Reveal** control to request a value through the individual-secret endpoint. The server checks that request's permissions separately from the record GET.

## CLI behavior

When retrieving a record without specifying a version, `ctxl records get` sends `doNotDecrypt=true`, so its response keeps stored secrets as `<ENCRYPTED>`, even for a caller with Update or Reveal permission. This differs from a direct API GET that omits the parameter.

Use `ctxl records reveal` with `--path` to request a specific value through the individual-secret endpoint. The same endpoint permissions apply. For example:

```bash
ctxl records get native-object:example/example-001
ctxl records reveal native-object:example/example-001 --path mySecretProperty
```

The reveal command prints the requested value. Keep that output out of shared terminal logs and AI session transcripts.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.contextual.io/documentation-and-resources/components-and-data/object-types/object-type-details/data-schema/secret.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
