# Secrets (/en/docs/api/native/vault/secrets)



Add, import and update write-only secrets; validation and refresh apply only to OAuth secrets.

[Guide →](/en/docs/developers/services/vault/quickstart)

[Base URL and authentication](/en/docs/api/native/vault)

Import replaces only the value of an existing name. Hosts change only from that line's own allowed\_hosts, never from top-level defaults. New lines use their own hosts or the top-level defaults. Per-line failures appear in failed under HTTP 200 (including SECRET\_TOO\_LARGE, VAULT\_LIMIT\_EXCEEDED and INVALID\_PARAMS); other lines are still written. Lookup by an invalid name returns 404 SECRET\_NOT\_FOUND.

## List secrets [#list-secrets]

`GET /vault/v1/vaults/{vault_id}/secrets`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| cursor | query | next_cursor from the previous page. |
| limit | query | Items per page. (default: 50) (1–200) |
| include_archived | query | Include archived items. (default: false) |

### Response [#response]

#### HTTP 200 [#http-200]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| data | Secret[] | yes | Result items |
| data[].id | string | yes | Object ID |
| data[].type | "vault_secret" | yes | Object type |
| data[].vault_id | string | yes | Vault ID |
| data[].name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| data[].kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| data[].allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| data[].description | string / null | yes | Description; null clears it on update, omission preserves it |
| data[].metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| data[].status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| data[].oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| data[].oauth.expires_at | date-time / null | yes | Expiry time, or null |
| data[].oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| data[].oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| data[].oauth.scope | string / null | yes | Granted scope, or null |
| data[].oauth.last_error | object / null | yes | Last refresh failure, or null |
| data[].oauth.last_error.code | string | yes | Stable error code |
| data[].oauth.last_error.message | string | yes | Human-readable error message |
| data[].oauth.last_error.at | date-time | yes | Event or error time |
| data[].version | integer | yes | Increments each time the value changes |
| data[].last_used_at | date-time / null | yes | Last use time, or null |
| data[].created_at | date-time | yes | Creation time |
| data[].updated_at | date-time | yes | Last update time |
| data[].archived_at | date-time / null | yes | Archive time, or null |
| next_cursor | string / null | yes | Next page cursor, or null |

### Error responses [#error-responses]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| INVALID_PARAMS | 400 | Invalid fields, names, hosts, metadata, pagination or return URL; correct the request | validation_failure | none | no |

```bash
curl "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets" \
  -H "Authorization: Bearer $PRAXIS_API_KEY"
```

## Create secret [#create-secret]

`POST /vault/v1/vaults/{vault_id}/secrets`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |

### Request body [#request-body]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| value | string | yes | Write-only secret value, at most 16 KiB |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | no | Description; null clears it on update, omission preserves it |
| metadata | object | no | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| template_id | "github" / "openai" / "anthropic" / "stripe" | no | Static template ID only; recorded as metadata.template |
| kind | "static" | no | Must be static; create OAuth secrets through authorization |

### Response [#response-1]

#### HTTP 200 [#http-200-1]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret" | yes | Object type |
| vault_id | string | yes | Vault ID |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | yes | Description; null clears it on update, omission preserves it |
| metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| oauth.expires_at | date-time / null | yes | Expiry time, or null |
| oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| oauth.scope | string / null | yes | Granted scope, or null |
| oauth.last_error | object / null | yes | Last refresh failure, or null |
| oauth.last_error.code | string | yes | Stable error code |
| oauth.last_error.message | string | yes | Human-readable error message |
| oauth.last_error.at | date-time | yes | Event or error time |
| version | integer | yes | Increments each time the value changes |
| last_used_at | date-time / null | yes | Last use time, or null |
| created_at | date-time | yes | Creation time |
| updated_at | date-time | yes | Last update time |
| archived_at | date-time / null | yes | Archive time, or null |

### Error responses [#error-responses-1]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| VAULT_INVALID_STATE | 409 | Writing to an archived vault or secret; use an active resource | validation_failure | none | no |
| INVALID_PARAMS | 400 | Invalid fields, names, hosts, metadata, pagination or return URL; correct the request | validation_failure | none | no |
| SECRET_CONFLICT | 409 | Name already exists on creation; rename or update the existing secret | validation_failure | none | no |
| VAULT_LIMIT_EXCEEDED | 400 | Active-secret limit exceeded; remove unused secrets | validation_failure | none | no |
| SECRET_TOO_LARGE | 413 | Value exceeds 16384 bytes; reduce its size | validation_failure | none | no |

```bash
curl -X POST "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"GITHUB_TOKEN","value":"ghp_example","allowed_hosts":["api.github.com"]}'
```

## Import secrets [#import-secrets]

`POST /vault/v1/vaults/{vault_id}/secrets:import`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |

### Request body [#request-body-1]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| lines | ImportLine[] | no | ImportLine entries |
| lines[].name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| lines[].value | string | yes | Write-only secret value, at most 16 KiB |
| lines[].allowed_hosts | string[] | no | New entries use line hosts or import defaults; replacements change hosts only with explicit per-line allowed_hosts |
| dotenv | string | no | KEY=VALUE lines; provide exactly one of dotenv or lines |
| allowed_hosts | string[] | no | New entries use line hosts or import defaults; replacements change hosts only with explicit per-line allowed_hosts |

### Response [#response-2]

#### HTTP 200 [#http-200-2]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| created | string[] | yes | Created secret names |
| replaced | string[] | yes | Replaced secret names |
| failed | object[] | yes | Failed import lines |
| failed[].line | integer | yes | Failed line number, starting at 1 |
| failed[].name | string / null | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| failed[].code | "VAULT_NOT_FOUND" / "SECRET_NOT_FOUND" / "AUTHORIZATION_NOT_FOUND" / "SECRET_CONFLICT" / "VAULT_INVALID_STATE" / "VAULT_LIMIT_EXCEEDED" / "INVALID_PARAMS" / "SECRET_KIND_MISMATCH" / "VALIDATE_UNSUPPORTED" / "SECRET_TOO_LARGE" / "RATE_LIMITED" / "AUTHORIZATION_EXPIRED" / "OAUTH_DISCOVERY_FAILED" / "OAUTH_REGISTRATION_UNSUPPORTED" / "OAUTH_ISSUER_MISMATCH" / "OAUTH_STATE_INVALID" / "OAUTH_EXCHANGE_FAILED" / "NOT_IMPLEMENTED" | yes | Stable error code |
| failed[].message | string | yes | Human-readable error message |

### Error responses [#error-responses-2]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| VAULT_INVALID_STATE | 409 | Writing to an archived vault or secret; use an active resource | validation_failure | none | no |
| INVALID_PARAMS | 400 | Invalid fields, names, hosts, metadata, pagination or return URL; correct the request | validation_failure | none | no |

```bash
curl -X POST "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets:import" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dotenv":"OPENAI_API_KEY=sk-example\nLINEAR_API_KEY=lin_example","allowed_hosts":["api.openai.com","api.linear.app"]}'
```

## Get secret [#get-secret]

`GET /vault/v1/vaults/{vault_id}/secrets/{secret}`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| secret | path | Secret name, or its vsec_ ID. |

### Response [#response-3]

#### HTTP 200 [#http-200-3]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret" | yes | Object type |
| vault_id | string | yes | Vault ID |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | yes | Description; null clears it on update, omission preserves it |
| metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| oauth.expires_at | date-time / null | yes | Expiry time, or null |
| oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| oauth.scope | string / null | yes | Granted scope, or null |
| oauth.last_error | object / null | yes | Last refresh failure, or null |
| oauth.last_error.code | string | yes | Stable error code |
| oauth.last_error.message | string | yes | Human-readable error message |
| oauth.last_error.at | date-time | yes | Event or error time |
| version | integer | yes | Increments each time the value changes |
| last_used_at | date-time / null | yes | Last use time, or null |
| created_at | date-time | yes | Creation time |
| updated_at | date-time | yes | Last update time |
| archived_at | date-time / null | yes | Archive time, or null |

### Error responses [#error-responses-3]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| SECRET_NOT_FOUND | 404 | Secret absent, including lookup by an invalid name; check name or ID | validation_failure | none | no |

```bash
curl "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets/GITHUB_TOKEN" \
  -H "Authorization: Bearer $PRAXIS_API_KEY"
```

## Update secret [#update-secret]

`POST /vault/v1/vaults/{vault_id}/secrets/{secret}`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| secret | path | Secret name, or its vsec_ ID. |

### Request body [#request-body-2]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| value | string | no | Write-only secret value, at most 16 KiB |
| allowed_hosts | string[] | no | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | no | Description; null clears it on update, omission preserves it |
| metadata | object | no | Merge by key: strings upsert, null deletes, omitted keys remain; source and template are reserved |

### Response [#response-4]

#### HTTP 200 [#http-200-4]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret" | yes | Object type |
| vault_id | string | yes | Vault ID |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | yes | Description; null clears it on update, omission preserves it |
| metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| oauth.expires_at | date-time / null | yes | Expiry time, or null |
| oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| oauth.scope | string / null | yes | Granted scope, or null |
| oauth.last_error | object / null | yes | Last refresh failure, or null |
| oauth.last_error.code | string | yes | Stable error code |
| oauth.last_error.message | string | yes | Human-readable error message |
| oauth.last_error.at | date-time | yes | Event or error time |
| version | integer | yes | Increments each time the value changes |
| last_used_at | date-time / null | yes | Last use time, or null |
| created_at | date-time | yes | Creation time |
| updated_at | date-time | yes | Last update time |
| archived_at | date-time / null | yes | Archive time, or null |

### Error responses [#error-responses-4]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| SECRET_NOT_FOUND | 404 | Secret absent, including lookup by an invalid name; check name or ID | validation_failure | none | no |
| VAULT_INVALID_STATE | 409 | Writing to an archived vault or secret; use an active resource | validation_failure | none | no |
| INVALID_PARAMS | 400 | Invalid fields, names, hosts, metadata, pagination or return URL; correct the request | validation_failure | none | no |
| SECRET_TOO_LARGE | 413 | Value exceeds 16384 bytes; reduce its size | validation_failure | none | no |

```bash
curl -X POST "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets/GITHUB_TOKEN" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value":"ghp_rotated"}'
```

## Delete secret [#delete-secret]

`DELETE /vault/v1/vaults/{vault_id}/secrets/{secret}`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| secret | path | Secret name, or its vsec_ ID. |

### Response [#response-5]

#### HTTP 200 [#http-200-5]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret_deleted" | yes | Object type |

### Error responses [#error-responses-5]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| SECRET_NOT_FOUND | 404 | Secret absent, including lookup by an invalid name; check name or ID | validation_failure | none | no |

```bash
curl -X DELETE "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets/GITHUB_TOKEN" \
  -H "Authorization: Bearer $PRAXIS_API_KEY"
```

## Archive secret [#archive-secret]

`POST /vault/v1/vaults/{vault_id}/secrets/{secret}/archive`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| secret | path | Secret name, or its vsec_ ID. |

### Response [#response-6]

#### HTTP 200 [#http-200-6]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret" | yes | Object type |
| vault_id | string | yes | Vault ID |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | yes | Description; null clears it on update, omission preserves it |
| metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| oauth.expires_at | date-time / null | yes | Expiry time, or null |
| oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| oauth.scope | string / null | yes | Granted scope, or null |
| oauth.last_error | object / null | yes | Last refresh failure, or null |
| oauth.last_error.code | string | yes | Stable error code |
| oauth.last_error.message | string | yes | Human-readable error message |
| oauth.last_error.at | date-time | yes | Event or error time |
| version | integer | yes | Increments each time the value changes |
| last_used_at | date-time / null | yes | Last use time, or null |
| created_at | date-time | yes | Creation time |
| updated_at | date-time | yes | Last update time |
| archived_at | date-time / null | yes | Archive time, or null |

### Error responses [#error-responses-6]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| SECRET_NOT_FOUND | 404 | Secret absent, including lookup by an invalid name; check name or ID | validation_failure | none | no |

```bash
curl -X POST "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets/GITHUB_TOKEN/archive" \
  -H "Authorization: Bearer $PRAXIS_API_KEY"
```

## Validate secret [#validate-secret]

`POST /vault/v1/vaults/{vault_id}/secrets/{secret}/validate`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| secret | path | Secret name, or its vsec_ ID. |

### Response [#response-7]

#### HTTP 200 [#http-200-7]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| type | "vault_secret_validation" | yes | Object type |
| secret_id | string | yes | Associated secret ID, or null |
| vault_id | string | yes | Vault ID |
| validated_at | date-time | yes | Validation time |
| has_refresh_token | boolean | yes | Whether a refresh token is stored |
| status | "valid" / "invalid" / "unknown" | yes | Current status |
| probe | object | yes | Resource probe |
| probe.method | "GET" | yes | Probe method, currently GET |
| probe.http_response | HttpCapture / null | yes | HTTP response summary, or null when no response was received |
| probe.http_response.status_code | integer | yes | HTTP status code |
| probe.http_response.content_type | string / null | yes | Response content type, or null |
| probe.http_response.body | string | yes | Redacted response body |
| probe.http_response.body_truncated | boolean | yes | Whether the body was truncated |
| refresh | object | yes | Refresh attempt |
| refresh.status | "succeeded" / "failed" / "connect_error" / "no_refresh_token" / "skipped" | yes | Current status |
| refresh.http_response | HttpCapture / null | yes | HTTP response summary, or null when no response was received |
| refresh.http_response.status_code | integer | yes | HTTP status code |
| refresh.http_response.content_type | string / null | yes | Response content type, or null |
| refresh.http_response.body | string | yes | Redacted response body |
| refresh.http_response.body_truncated | boolean | yes | Whether the body was truncated |

### Error responses [#error-responses-7]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| SECRET_NOT_FOUND | 404 | Secret absent, including lookup by an invalid name; check name or ID | validation_failure | none | no |
| VALIDATE_UNSUPPORTED | 400 | Validating a static secret; only OAuth secrets support validation | validation_failure | none | no |
| RATE_LIMITED | 429 | Authorization or validation minute quota exceeded; wait for the next window | rate_limit | wait_then_retry | yes |

OAuth secrets only. Complete authorization and set OAUTH\_SECRET\_ID to its secret\_id before running this example; do not use a static secret.

```bash
curl -X POST "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets/${OAUTH_SECRET_ID}/validate" \
  -H "Authorization: Bearer $PRAXIS_API_KEY"
```

## Refresh secret [#refresh-secret]

`POST /vault/v1/vaults/{vault_id}/secrets/{secret}/refresh`

| Parameter | Location | Description |
| --- | --- | --- |
| vault_id | path | ID of the vault in your account, returned when the vault is created. |
| secret | path | Secret name, or its vsec_ ID. |

### Request body [#request-body-3]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| reason | "unauthorized" | no | unauthorized: the resource returned HTTP 401 |

### Response [#response-8]

#### HTTP 200 [#http-200-8]

**application/json**

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret" | yes | Object type |
| vault_id | string | yes | Vault ID |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | yes | Description; null clears it on update, omission preserves it |
| metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| oauth.expires_at | date-time / null | yes | Expiry time, or null |
| oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| oauth.scope | string / null | yes | Granted scope, or null |
| oauth.last_error | object / null | yes | Last refresh failure, or null |
| oauth.last_error.code | string | yes | Stable error code |
| oauth.last_error.message | string | yes | Human-readable error message |
| oauth.last_error.at | date-time | yes | Event or error time |
| version | integer | yes | Increments each time the value changes |
| last_used_at | date-time / null | yes | Last use time, or null |
| created_at | date-time | yes | Creation time |
| updated_at | date-time | yes | Last update time |
| archived_at | date-time / null | yes | Archive time, or null |

### Error responses [#error-responses-8]

A missing or invalid API Key returns 401 UNAUTHENTICATED.

| Code | HTTP | Meaning, trigger and action | kind | recovery | Retryable |
| --- | --- | --- | --- | --- | --- |
| VAULT_NOT_FOUND | 404 | Vault absent or outside this account; check the vault ID | validation_failure | none | no |
| SECRET_NOT_FOUND | 404 | Secret absent, including lookup by an invalid name; check name or ID | validation_failure | none | no |
| VAULT_INVALID_STATE | 409 | Writing to an archived vault or secret; use an active resource | validation_failure | none | no |
| SECRET_KIND_MISMATCH | 400 | Refreshing a static secret or another kind mismatch; use an OAuth secret | validation_failure | none | no |
| INVALID_PARAMS | 400 | Invalid fields, names, hosts, metadata, pagination or return URL; correct the request | validation_failure | none | no |

OAuth secrets only. Complete authorization and set OAUTH\_SECRET\_ID to its secret\_id before running this example; do not use a static secret.

```bash
curl -X POST "https://api.deepraxis.ai/vault/v1/vaults/${VAULT_ID}/secrets/${OAUTH_SECRET_ID}/refresh" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"unauthorized"}'
```

## Secret [#secret]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| id | string | yes | Object ID |
| type | "vault_secret" | yes | Object type |
| vault_id | string | yes | Vault ID |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| kind | "static" / "oauth" | yes | static: supplied value; oauth: authorized and refreshed by the platform |
| allowed_hosts | string[] | yes | 1–16 hosts, public IPv4 addresses or *.example.com (excluding the apex). Rejects IPv6, single-label hosts, localhost, *.internal, platform domains and loopback/link-local/private/CGNAT IPv4; normalized and deduplicated |
| description | string / null | yes | Description; null clears it on update, omission preserves it |
| metadata | object | yes | Up to 16 caller labels. System keys source and template are reserved and excluded from that limit |
| status | "active" / "refreshing" / "refresh_failed" / "archived" | yes | Current status |
| oauth | SecretOAuthSummary / null | yes | OAuth summary; null for static secrets |
| oauth.expires_at | date-time / null | yes | Expiry time, or null |
| oauth.last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| oauth.next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| oauth.scope | string / null | yes | Granted scope, or null |
| oauth.last_error | object / null | yes | Last refresh failure, or null |
| oauth.last_error.code | string | yes | Stable error code |
| oauth.last_error.message | string | yes | Human-readable error message |
| oauth.last_error.at | date-time | yes | Event or error time |
| version | integer | yes | Increments each time the value changes |
| last_used_at | date-time / null | yes | Last use time, or null |
| created_at | date-time | yes | Creation time |
| updated_at | date-time | yes | Last update time |
| archived_at | date-time / null | yes | Archive time, or null |

## SecretOAuthSummary [#secretoauthsummary]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| expires_at | date-time / null | yes | Expiry time, or null |
| last_refreshed_at | date-time / null | yes | Last refresh time, or null |
| next_refresh_at | date-time / null | yes | Next scheduled refresh, or null |
| scope | string / null | yes | Granted scope, or null |
| last_error | object / null | yes | Last refresh failure, or null |
| last_error.code | string | yes | Stable error code |
| last_error.message | string | yes | Human-readable error message |
| last_error.at | date-time | yes | Event or error time |

## ImportLine [#importline]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| name | string | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| value | string | yes | Write-only secret value, at most 16 KiB |
| allowed_hosts | string[] | no | New entries use line hosts or import defaults; replacements change hosts only with explicit per-line allowed_hosts |

## ImportResult [#importresult]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| created | string[] | yes | Created secret names |
| replaced | string[] | yes | Replaced secret names |
| failed | object[] | yes | Failed import lines |
| failed[].line | integer | yes | Failed line number, starting at 1 |
| failed[].name | string / null | yes | Secret name: 1–128 uppercase letters, digits or underscores; starts with a letter or underscore |
| failed[].code | "VAULT_NOT_FOUND" / "SECRET_NOT_FOUND" / "AUTHORIZATION_NOT_FOUND" / "SECRET_CONFLICT" / "VAULT_INVALID_STATE" / "VAULT_LIMIT_EXCEEDED" / "INVALID_PARAMS" / "SECRET_KIND_MISMATCH" / "VALIDATE_UNSUPPORTED" / "SECRET_TOO_LARGE" / "RATE_LIMITED" / "AUTHORIZATION_EXPIRED" / "OAUTH_DISCOVERY_FAILED" / "OAUTH_REGISTRATION_UNSUPPORTED" / "OAUTH_ISSUER_MISMATCH" / "OAUTH_STATE_INVALID" / "OAUTH_EXCHANGE_FAILED" / "NOT_IMPLEMENTED" | yes | Stable error code |
| failed[].message | string | yes | Human-readable error message |

## SecretValidation [#secretvalidation]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| type | "vault_secret_validation" | yes | Object type |
| secret_id | string | yes | Associated secret ID, or null |
| vault_id | string | yes | Vault ID |
| validated_at | date-time | yes | Validation time |
| has_refresh_token | boolean | yes | Whether a refresh token is stored |
| status | "valid" / "invalid" / "unknown" | yes | Current status |
| probe | object | yes | Resource probe |
| probe.method | "GET" | yes | Probe method, currently GET |
| probe.http_response | HttpCapture / null | yes | HTTP response summary, or null when no response was received |
| probe.http_response.status_code | integer | yes | HTTP status code |
| probe.http_response.content_type | string / null | yes | Response content type, or null |
| probe.http_response.body | string | yes | Redacted response body |
| probe.http_response.body_truncated | boolean | yes | Whether the body was truncated |
| refresh | object | yes | Refresh attempt |
| refresh.status | "succeeded" / "failed" / "connect_error" / "no_refresh_token" / "skipped" | yes | Current status |
| refresh.http_response | HttpCapture / null | yes | HTTP response summary, or null when no response was received |
| refresh.http_response.status_code | integer | yes | HTTP status code |
| refresh.http_response.content_type | string / null | yes | Response content type, or null |
| refresh.http_response.body | string | yes | Redacted response body |
| refresh.http_response.body_truncated | boolean | yes | Whether the body was truncated |

## HttpCapture [#httpcapture]

| Field | Type / enum | Required | Description |
| --- | --- | --- | --- |
| status_code | integer | yes | HTTP status code |
| content_type | string / null | yes | Response content type, or null |
| body | string | yes | Redacted response body |
| body_truncated | boolean | yes | Whether the body was truncated |
