# Secrets

Soda Cloud API Secret Endpoints

## List secrets

> This endpoint allows you to list secrets in your organization.\
> \
> This GET is a paginated API that uses the following parameters to request specific details:\
> \
> \- \`size\`: Supply an integer value between 10 and 1000, inclusive. The default value is 10.\
> \
> \- \`page\`: Supply an integer value. The default value is 0.\
> \
> \- \`search\`: Supply a string value to filter secrets by name (case-insensitive partial match).\
> \
> \## Authentication\
> \
> User authentication required: \`true\`\
> \
> This endpoint enforces authentication using the API keys you provide in the \`Basic\` authentication header.\
> \
> \## Authorization\
> \
> Users must have global role permission MANAGE\_DATASOURCES\_AND\_AGENTS to execute this call.\
> \
> \## Tags\
> \
> \`Secrets\`\
> \
> \## Rate limiting\
> \
> 60 requests/60 seconds

```json
{"openapi":"3.1.0","info":{"title":"Soda Cloud API v4","version":"v1"},"tags":[{"description":"Soda Cloud API Secret Endpoints","name":"Secrets"}],"servers":[{"description":"Cloud EU","url":"https://cloud.soda.io"},{"description":"Cloud US","url":"https://cloud.us.soda.io"}],"security":[{"basicAuthApiKey":[]}],"components":{"securitySchemes":{"basicAuthApiKey":{"scheme":"basic","type":"http"}},"schemas":{"PublicApiListSecretsResponse":{"type":"object","properties":{"content":{"type":"array","items":{"type":"object","$ref":"#/components/schemas/PublicApiSecretDTO"}},"first":{"type":"boolean"},"last":{"type":"boolean"},"number":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int32"},"totalPages":{"type":"integer","format":"int32"}},"required":["content","first","last","number","size","totalElements","totalPages"]},"PublicApiSecretDTO":{"type":"object","properties":{"created":{"type":"string","format":"date-time"},"id":{"type":"string"},"lastUpdated":{"type":"string","format":"date-time"},"name":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"paths":{"/api/v1/secrets":{"get":{"description":"This endpoint allows you to list secrets in your organization.\n\nThis GET is a paginated API that uses the following parameters to request specific details:\n\n- `size`: Supply an integer value between 10 and 1000, inclusive. The default value is 10.\n\n- `page`: Supply an integer value. The default value is 0.\n\n- `search`: Supply a string value to filter secrets by name (case-insensitive partial match).\n\n## Authentication\n\nUser authentication required: `true`\n\nThis endpoint enforces authentication using the API keys you provide in the `Basic` authentication header.\n\n## Authorization\n\nUsers must have global role permission MANAGE_DATASOURCES_AND_AGENTS to execute this call.\n\n## Tags\n\n`Secrets`\n\n## Rate limiting\n\n60 requests/60 seconds","operationId":"GET/api/v1/secrets","parameters":[{"in":"query","name":"page","schema":{"type":"integer","format":"int32"}},{"in":"query","name":"search","schema":{"type":"string"}},{"in":"query","name":"size","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiListSecretsResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"429":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too many requests"},"500":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal server error"}},"summary":"List secrets","tags":["Secrets"]}}}}
```

## Create a secret

> Creates a new secret in your organization. Secrets store encrypted credentials that can be referenced in datasource configurations using \`${secret.NAME}\` placeholders, keeping sensitive values out of plain text.\
> \
> \## Encryption\
> \
> Secret values must be encrypted \*\*client-side\*\* before sending them to this endpoint. This enables a zero-trust design, where Soda never decrypts the secret. Decryption happens only during scan execution, within the runner.\
> \
> Use the \`GET /api/v1/secretsPublicKey\` endpoint to obtain the server's RSA public key. The encryption uses a two-layer scheme:\
> \
> 1\. Fetch the RSA public key from \`GET /api/v1/secretsPublicKey\`.\
> \
> 2\. Generate a random AES-256-GCM key (32 bytes) and initialization vector (IV, 12 bytes).\
> \
> 3\. Encrypt the secret value using AES-256-GCM with the generated key and IV. Base64-encode the ciphertext and prefix it with \`encrypted\_\`. This becomes the \`encryptedValue\` field.\
> \
> 4\. Export the raw AES key and IV as base64 strings and concatenate them as \`{base64\_key}:::{base64\_iv}\`. Encrypt this string using RSA-OAEP (SHA-256) with the public key from step 1. Base64-encode the result. This becomes the \`encryptionKey\` field.\
> \
> \## Constraints\
> \
> \- The secret \`name\` must not contain whitespace and must be unique within the organization.\
> \
> \- Both \`encryptionKey\` and \`encryptedValue\` are required.\
> \
> \- The organization must have the contracts feature enabled and the secure store must not be disabled.\
> \
> \## Authentication\
> \
> User authentication required: \`true\`\
> \
> This endpoint enforces authentication using the API keys you provide in the \`Basic\` authentication header.\
> \
> \## Authorization\
> \
> Users must have global role permission MANAGE\_DATASOURCES\_AND\_AGENTS to execute this call.\
> \
> \## Tags\
> \
> \`Secrets\`\
> \
> \## Rate limiting\
> \
> 10 requests/60 seconds

```json
{"openapi":"3.1.0","info":{"title":"Soda Cloud API v4","version":"v1"},"tags":[{"description":"Soda Cloud API Secret Endpoints","name":"Secrets"}],"servers":[{"description":"Cloud EU","url":"https://cloud.soda.io"},{"description":"Cloud US","url":"https://cloud.us.soda.io"}],"security":[{"basicAuthApiKey":[]}],"components":{"securitySchemes":{"basicAuthApiKey":{"scheme":"basic","type":"http"}},"schemas":{"PublicApiCreateSecretRequestDTO":{"type":"object","properties":{"encryptedValue":{"type":"string"},"encryptionKey":{"type":"string"},"name":{"type":"string"}},"required":["encryptedValue","encryptionKey","name"]},"PublicApiCreateSecretResponse":{"type":"object","properties":{"secret":{"type":"object","$ref":"#/components/schemas/PublicApiSecretDTO"}}},"PublicApiSecretDTO":{"type":"object","properties":{"created":{"type":"string","format":"date-time"},"id":{"type":"string"},"lastUpdated":{"type":"string","format":"date-time"},"name":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"paths":{"/api/v1/secrets":{"post":{"description":"Creates a new secret in your organization. Secrets store encrypted credentials that can be referenced in datasource configurations using `${secret.NAME}` placeholders, keeping sensitive values out of plain text.\n\n## Encryption\n\nSecret values must be encrypted **client-side** before sending them to this endpoint. This enables a zero-trust design, where Soda never decrypts the secret. Decryption happens only during scan execution, within the runner.\n\nUse the `GET /api/v1/secretsPublicKey` endpoint to obtain the server's RSA public key. The encryption uses a two-layer scheme:\n\n1. Fetch the RSA public key from `GET /api/v1/secretsPublicKey`.\n\n2. Generate a random AES-256-GCM key (32 bytes) and initialization vector (IV, 12 bytes).\n\n3. Encrypt the secret value using AES-256-GCM with the generated key and IV. Base64-encode the ciphertext and prefix it with `encrypted_`. This becomes the `encryptedValue` field.\n\n4. Export the raw AES key and IV as base64 strings and concatenate them as `{base64_key}:::{base64_iv}`. Encrypt this string using RSA-OAEP (SHA-256) with the public key from step 1. Base64-encode the result. This becomes the `encryptionKey` field.\n\n## Constraints\n\n- The secret `name` must not contain whitespace and must be unique within the organization.\n\n- Both `encryptionKey` and `encryptedValue` are required.\n\n- The organization must have the contracts feature enabled and the secure store must not be disabled.\n\n## Authentication\n\nUser authentication required: `true`\n\nThis endpoint enforces authentication using the API keys you provide in the `Basic` authentication header.\n\n## Authorization\n\nUsers must have global role permission MANAGE_DATASOURCES_AND_AGENTS to execute this call.\n\n## Tags\n\n`Secrets`\n\n## Rate limiting\n\n10 requests/60 seconds","operationId":"POST/api/v1/secrets","requestBody":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiCreateSecretRequestDTO"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiCreateSecretResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"429":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too many requests"},"500":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal server error"}},"summary":"Create a secret","tags":["Secrets"]}}}}
```

## Update a secret

> Updates the encrypted value of an existing secret. The secret name cannot be changed.\
> \
> Both \`encryptionKey\` and \`encryptedValue\` must be provided together — you cannot update one without the other.\
> \
> \## Encryption\
> \
> The new secret value must be encrypted \*\*client-side\*\* using the same two-layer encryption scheme as creation. See the \`POST /api/v1/secrets\` (Create a secret) endpoint for the full encryption workflow.\
> \
> \## Authentication\
> \
> User authentication required: \`true\`\
> \
> This endpoint enforces authentication using the API keys you provide in the \`Basic\` authentication header.\
> \
> \## Authorization\
> \
> Users must have global role permission MANAGE\_DATASOURCES\_AND\_AGENTS to execute this call.\
> \
> \## Tags\
> \
> \`Secrets\`\
> \
> \## Rate limiting\
> \
> 100 requests/60 seconds

```json
{"openapi":"3.1.0","info":{"title":"Soda Cloud API v4","version":"v1"},"tags":[{"description":"Soda Cloud API Secret Endpoints","name":"Secrets"}],"servers":[{"description":"Cloud EU","url":"https://cloud.soda.io"},{"description":"Cloud US","url":"https://cloud.us.soda.io"}],"security":[{"basicAuthApiKey":[]}],"components":{"securitySchemes":{"basicAuthApiKey":{"scheme":"basic","type":"http"}},"schemas":{"PublicApiUpdateSecretRequestDTO":{"type":"object","properties":{"encryptedValue":{"type":"string"},"encryptionKey":{"type":"string"}},"required":["encryptedValue","encryptionKey"]},"PublicApiUpdateSecretResponse":{"type":"object","properties":{"secret":{"type":"object","$ref":"#/components/schemas/PublicApiSecretDTO"}}},"PublicApiSecretDTO":{"type":"object","properties":{"created":{"type":"string","format":"date-time"},"id":{"type":"string"},"lastUpdated":{"type":"string","format":"date-time"},"name":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"paths":{"/api/v1/secrets/{secretId}":{"post":{"description":"Updates the encrypted value of an existing secret. The secret name cannot be changed.\n\nBoth `encryptionKey` and `encryptedValue` must be provided together — you cannot update one without the other.\n\n## Encryption\n\nThe new secret value must be encrypted **client-side** using the same two-layer encryption scheme as creation. See the `POST /api/v1/secrets` (Create a secret) endpoint for the full encryption workflow.\n\n## Authentication\n\nUser authentication required: `true`\n\nThis endpoint enforces authentication using the API keys you provide in the `Basic` authentication header.\n\n## Authorization\n\nUsers must have global role permission MANAGE_DATASOURCES_AND_AGENTS to execute this call.\n\n## Tags\n\n`Secrets`\n\n## Rate limiting\n\n100 requests/60 seconds","operationId":"POST/api/v1/secrets/{secretId}","parameters":[{"in":"path","name":"secretId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiUpdateSecretRequestDTO"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiUpdateSecretResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"429":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too many requests"},"500":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal server error"}},"summary":"Update a secret","tags":["Secrets"]}}}}
```

## Delete a secret

> Deletes an existing secret.\
> \
> The secret cannot be deleted if it is referenced by a datasource configuration.\
> \
> \## Authentication\
> \
> User authentication required: \`true\`\
> \
> This endpoint enforces authentication using the API keys you provide in the \`Basic\` authentication header.\
> \
> \## Authorization\
> \
> Users must have global role permission MANAGE\_DATASOURCES\_AND\_AGENTS to execute this call.\
> \
> \## Tags\
> \
> \`Secrets\`\
> \
> \## Rate limiting\
> \
> 10 requests/60 seconds

```json
{"openapi":"3.1.0","info":{"title":"Soda Cloud API v4","version":"v1"},"tags":[{"description":"Soda Cloud API Secret Endpoints","name":"Secrets"}],"servers":[{"description":"Cloud EU","url":"https://cloud.soda.io"},{"description":"Cloud US","url":"https://cloud.us.soda.io"}],"security":[{"basicAuthApiKey":[]}],"components":{"securitySchemes":{"basicAuthApiKey":{"scheme":"basic","type":"http"}},"schemas":{"PublicApiDeleteSecretResponse":{"type":"object","properties":{"message":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"paths":{"/api/v1/secrets/{secretId}":{"delete":{"description":"Deletes an existing secret.\n\nThe secret cannot be deleted if it is referenced by a datasource configuration.\n\n## Authentication\n\nUser authentication required: `true`\n\nThis endpoint enforces authentication using the API keys you provide in the `Basic` authentication header.\n\n## Authorization\n\nUsers must have global role permission MANAGE_DATASOURCES_AND_AGENTS to execute this call.\n\n## Tags\n\n`Secrets`\n\n## Rate limiting\n\n10 requests/60 seconds","operationId":"DELETE/api/v1/secrets/{secretId}","parameters":[{"in":"path","name":"secretId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiDeleteSecretResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"429":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too many requests"},"500":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal server error"}},"summary":"Delete a secret","tags":["Secrets"]}}}}
```

## Get the encryption public key

> Returns the RSA public key in JWK (JSON Web Key) format, used for client-side encryption of secret values.\
> \
> \## Usage\
> \
> When creating or updating a secret, the secret value must be encrypted client-side before sending it to the API. This endpoint provides the RSA public key needed for that encryption.\
> \
> \## Encryption workflow\
> \
> 1\. Fetch this public key.\
> \
> 2\. Generate a random AES-256-GCM key (32 bytes) and initialization vector (IV, 12 bytes).\
> \
> 3\. Encrypt the secret value using AES-256-GCM with the generated key and IV. Base64-encode the ciphertext and prefix it with \`encrypted\_\`. This becomes the \`encryptedValue\` field.\
> \
> 4\. Export the raw AES key and IV as base64 strings and concatenate them as \`{base64\_key}:::{base64\_iv}\`. Encrypt this string using RSA-OAEP (SHA-256) with this public key. Base64-encode the result. This becomes the \`encryptionKey\` field.\
> \
> 5\. Use the \`encryptedValue\` and \`encryptionKey\` in the create or update secret request.\
> \
> \## Authentication\
> \
> User authentication required: \`true\`\
> \
> This endpoint enforces authentication using the API keys you provide in the \`Basic\` authentication header.\
> \
> \## Authorization\
> \
> Users must have global role permission MANAGE\_DATASOURCES\_AND\_AGENTS to execute this call.\
> \
> \## Tags\
> \
> \`Secrets\`\
> \
> \## Rate limiting\
> \
> 60 requests/60 seconds

```json
{"openapi":"3.1.0","info":{"title":"Soda Cloud API v4","version":"v1"},"tags":[{"description":"Soda Cloud API Secret Endpoints","name":"Secrets"}],"servers":[{"description":"Cloud EU","url":"https://cloud.soda.io"},{"description":"Cloud US","url":"https://cloud.us.soda.io"}],"security":[{"basicAuthApiKey":[]}],"components":{"securitySchemes":{"basicAuthApiKey":{"scheme":"basic","type":"http"}},"schemas":{"PublicApiGetEncryptionKeyResponse":{"type":"object","properties":{"encryptionKey":{"type":"object","$ref":"#/components/schemas/MapOfStringTo_object"}}},"MapOfStringTo_object":{"type":"object","additionalProperties":true},"ErrorResponse":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"paths":{"/api/v1/secretsPublicKey":{"get":{"description":"Returns the RSA public key in JWK (JSON Web Key) format, used for client-side encryption of secret values.\n\n## Usage\n\nWhen creating or updating a secret, the secret value must be encrypted client-side before sending it to the API. This endpoint provides the RSA public key needed for that encryption.\n\n## Encryption workflow\n\n1. Fetch this public key.\n\n2. Generate a random AES-256-GCM key (32 bytes) and initialization vector (IV, 12 bytes).\n\n3. Encrypt the secret value using AES-256-GCM with the generated key and IV. Base64-encode the ciphertext and prefix it with `encrypted_`. This becomes the `encryptedValue` field.\n\n4. Export the raw AES key and IV as base64 strings and concatenate them as `{base64_key}:::{base64_iv}`. Encrypt this string using RSA-OAEP (SHA-256) with this public key. Base64-encode the result. This becomes the `encryptionKey` field.\n\n5. Use the `encryptedValue` and `encryptionKey` in the create or update secret request.\n\n## Authentication\n\nUser authentication required: `true`\n\nThis endpoint enforces authentication using the API keys you provide in the `Basic` authentication header.\n\n## Authorization\n\nUsers must have global role permission MANAGE_DATASOURCES_AND_AGENTS to execute this call.\n\n## Tags\n\n`Secrets`\n\n## Rate limiting\n\n60 requests/60 seconds","operationId":"GET/api/v1/secretsPublicKey","responses":{"200":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/PublicApiGetEncryptionKeyResponse"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"429":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too many requests"},"500":{"content":{"application/json":{"schema":{"type":"object","$ref":"#/components/schemas/ErrorResponse"}}},"description":"Internal server error"}},"summary":"Get the encryption public key","tags":["Secrets"]}}}}
```
