# Keeper Notation

## About

Keeper notation is used by Keeper Secrets Manager[ SDKs](https://docs.keeper.io/en/keeperpam/secrets-manager/developer-sdk-library) and [integrations](https://docs.keeper.io/en/keeperpam/secrets-manager/integrations) to query fields in Keeper records. To view the different types of records and the field names available, [click here](https://docs.keeper.io/en/keeperpam/secrets-manager/about/field-record-types).

## Notation

{% tabs %}
{% tab title="Format" %}
**`keeper://<TITLE|UID>/<type|title|notes>`**

**`keeper://<TITLE|UID>/file/<filename|title|fileUID>`**

**`keeper://<TITLE|UID>/<field|custom_field>/<label|type>[[predicate1][predicate2]]`**

The notation is broken up into four parts.

* Title or UID of the secret record
* The selector of the record data. There are three types:
  * short selectors without any additional parameters - **type**, **title**, and **notes**
  * **file** selector accepts a single parameter - file **name**, **title** or **UID**
  * full selector specifies the filed type - **field** or **custom\_field**, and requires additional parameters
* The parameters used for full selectors must specify the field **type** or **label** that selects a unique field in the record, and predicates are optional
* The predicates are optional indexes further into field value. The first predicate is the numeric index into the value array, and the second index is a property index (in case of a complex value)- *ex. .../custom\_field/name\[1]\[middle]*

{% hint style="warning" %}
The first predicate is always required in order to use the second predicate. Please use one of the following examples:\
`phone[0][number]` - get only the first number for the first phone (even if the array contains only one phone)\
`phone[][number]` - get a CSV list of all numbers from all phones in the value array
{% endhint %}

#### **Predicates**

The predicate allows finer access to the value. Some values might be a single value or an array of values, and each of those values might be a string or a dictionary of values.

**Arrays**\
If no predicate is defined only one value will be returned.\
If the returned value contains an array of values, only the first one will be returned.\
If a predicate with a number is defined, e.g. `phone[0]` the value at that index is returned.\
Indexes start at 0.

If a predicate with no value is defined, e.g. `phone[]`, the array value will be returned.

**Sub Fields**\
Some field values are made up of other sub fields.\
For example:

<pre><code><strong>"fields": [
</strong>    { "type": "name", "value": [ 
        {"first:": "John", "last": "Doe"},
        {"first:": "Jane", "last": "Doe"} ]
    },
    { "type": "phone", "value": [
        {"number": "555-5555555", "ext": "55"}, 
        {"number": "777-7777777", "ext": "77"} ]
    }
]
</code></pre>

To access sub fields, include the name of the field as an alphanumeric predicate.\
For example `name[0][first]` will find "John" in the example above, and `name[1][first]` will find "Jane".

**Mixed**

Some values are a combination of the arrays and Sub Fields.\
For example:

```
[
    {"number": "555-5555555", "ext": "55"}, 
    {"number": "777-7777777", "ext": "77"}, 
    {"number": "888-8888888", "ext": "", "type": "Home"}, 
    {"number": "999-9999999", "type": "Work"}
]
```

To get a specific value you can use the first numeric predicate to get the whole value - ex. `phone[1]` will return the full value for the second phone `{"number": "777-7777777", "ext": "77"}`\
To get a specific sub field, a double predicate is needed. For example, the predicate `phone[1][number]` will return only the phone number of the second value.
{% endtab %}

{% tab title="Examples" %}
Use these examples as a reference for writing Keeper Notation queries. Note that each of these examples use a sample record UID.

{% hint style="warning" %}
*Replace the UID in examples with the record UID for your own record when utilizing Keeper Notation*
{% endhint %}

**Query the type, title or notes from a record**\
`keeper://EG6KdJaaLG7esRZbMnfbFA/type`\
`keeper://EG6KdJaaLG7esRZbMnfbFA/title`\
`keeper://EG6KdJaaLG7esRZbMnfbFA/notes`

**Query the password from a login record**\
`keeper://EG6KdJaaLG7esRZbMnfbFA/field/password`\
\&#xNAN;*returns:* `RX$u!h!pBzDGhR4Jr6#b` *(Randomly generated password from record)*

**Query the first name from a contact record**\
`keeper://3FXqmP5nFKwju0H8pl0DmQ/field/name[first]`

*returns:* `'Craig'`

**Query a file from a record**\
`keeper://bf3dg-99-JuhoaeswgtFxg/file/credentials.txt`

*returns:* `b"jNxmJkhbZ[...]6jQtE"` *(contents of credentials.txt)*

**Query a custom Pin Code field with the label 'code'**

`keeper://aj3dg-9ecJuhoa-sdyehg/custom_field/code`

*returns:* `5876` *(pin code)*

**Query a Two-Factor Code field from a login record**

`keeper://aj3dg-9ecJuhoa-sdyehg/field/oneTimeCode`

*returns:* `5876891`

**Query the 2nd of several custom field phone numbers**

`keeper://aj3dg-9ecJuhoa-sdyehg/custom_field/phone[1]`

*returns:* `{"number": "555-555-5555", "type": "home"}`

Get just the number of this phone field

`keeper://aj3dg-9ecJuhoa-sdyehg/custom_field/phone[1][number]`

*returns:* `"555-555-5555"`

Get all phone numbers on the record as an array

`keeper://aj3dg-9ecJuhoa-sdyehg/custom_field/phone[]`

*returns:*

```javascript
[
  {"number": "123-456-7890", "type": "work"},
  {"number": "555-555-5555", "type": "home"}
]
```

{% endtab %}
{% endtabs %}

## Fetching Records by Name

Keeper Secrets Manager SDKs support Keeper Notation fetching of records by record name.

### Escaping notation characters

If any part of the record contains "/" "\\" "\[" or "]" you will need to escape that character with a backslash. These special characters are used by notation as internal section and index delimiters and need to be escaped if present in the record title, field label or file name.

Examples:

*Title: "Twitter Login \[Marketing]"*\
`keeper://Twitter Login \[Marketing\]/field/password`\
\&#xNAN;*URL custom field with Label: "/. links"*\
`keeper://My Slashdot Links/custom_field/\/.links[]` *(all links)*\
`keeper://My Slashdot Links/custom_field/\/.links[1]` *(2nd link only)*\
\&#xNAN;*File name: "creds\[2].crt"*\
`keeper://My \/. Credentials/file/creds\[2\].crt`

### Using Name to Simplify Environment Switching

With the Keeper Notation record title fetching capability, it is possible to create your notation queries once, and use them across different build environments by utilizing different Secrets Manager Applications.

Example:

In this example, two shared folders have been created. One for developer environments and one for production. Inside each folder there are identically named records. These records have the same name, but different credentials stored in them.

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2Fgit-blob-a4c24604549694c56d6e2f606d2ec31f66367729%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

Each shared folder will be associated with a different Secrets Manager application.

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FOUqcK3KX7JJbPhxAYyVW%2Fimage.png?alt=media&#x26;token=b432dfc0-28e7-45e7-a4fc-4040c0b3c55f" alt=""><figcaption></figcaption></figure>

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FJeDMgxjkyrhxdqJe7Ys1%2Fimage.png?alt=media&#x26;token=f964ef4e-a644-42c8-b7cd-bb2c81403fba" alt=""><figcaption></figcaption></figure>

In the associated Secrets Manager integration, use notation to fetch the credentials. For example:\
`keeper://MySQL Creds/field/password`\
\
In integrations used for development builds, use the Secrets Manager application associated to the Dev folder (in this case "Development Environment"). Then to build for production, simply change the associated Secrets Manager application to "Production Environment" no change in code or scripts needed.


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/en/keeperpam/secrets-manager/about/keeper-notation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
