Skip to content

Vault API — Front-End Integration Guide

This document covers every vault endpoint, request/response shapes, the reference resolution mechanism, and the UI patterns you will need to implement.

The vault is a centralised, encrypted-at-rest store for secrets (API keys, SMTP passwords, tokens) and variables (base URLs, feature flags, shared config values). Once stored, secrets and variables can be referenced in plugin instance configurations and workflow input mappings using the $secret:<key> and $var:<key> syntax — the server resolves them at runtime so plaintext credentials never appear in config payloads.

All endpoints require the admin or integration role and accept either Authorization: Bearer <token> or X-API-KEY: <key>.


Table of Contents

Vault Entries

  1. Create a Vault Entry
  2. List Vault Entries
  3. Get a Single Vault Entry
  4. Update a Vault Entry
  5. Delete a Vault Entry

Reference Resolution

  1. Using References in Plugin Configs
  2. Using References in Workflow Input Mappings
  3. Reference Syntax Rules

Operations

  1. Environment Setup
  2. Important UI Considerations

1. Create a Vault Entry

POST /api/v1/vault_entry

Request Body

FieldTypeRequiredDefaultNotes
keystringyesUnique lookup key (e.g. smtp_password). Used in $secret:<key> and $var:<key> references
kindstringyesSECRET or VAR
valuestringyesThe plaintext value. Encrypted server-side when kind is SECRET
descriptionstringnonullOptional human-readable description
enabledbooleannotrueWhen false, references to this entry fail resolution

Response (200)

json
{
  "id": "ve-abc-123",
  "key": "smtp_password",
  "kind": "SECRET",
  "value": "******",
  "description": "SMTP server password for outbound emails",
  "enabled": true,
  "created_at": "2026-02-28T10:00:00Z",
  "updated_at": null,
  "deleted_at": null
}

**SECRET values are always masked as "\*\*\*\***" in API responses.** The plaintext is encrypted with Fernet (AES-128-CBC) before storage and is never returned via the API. VAR values are returned in plaintext.

Errors

StatusCodeWhen
409VAULT.KEY_EXISTSA vault entry with this key already exists

2. List Vault Entries

GET /api/v1/vault_entry

Query Parameters

ParamTypeDefaultNotes
limitinteger25Min 1
offsetinteger0Min 0
kindstringFilter by SECRET or VAR
keystringFilter by key (partial match)
enabledbooleanFilter by enabled flag
searchstringText search on key and description
sort_bystringField to sort by (e.g. key, created_at)
sort_dirstringascasc or desc

Response (200)

json
{
  "vault_entries": [
    {
      "id": "ve-abc-123",
      "key": "smtp_password",
      "kind": "SECRET",
      "value": "******",
      "description": "SMTP server password",
      "enabled": true,
      "created_at": "2026-02-28T10:00:00Z",
      "updated_at": null,
      "deleted_at": null
    },
    {
      "id": "ve-def-456",
      "key": "api_base_url",
      "kind": "VAR",
      "value": "https://api.example.com",
      "description": "Base URL for external API calls",
      "enabled": true,
      "created_at": "2026-02-28T09:00:00Z",
      "updated_at": null,
      "deleted_at": null
    }
  ],
  "total": 2,
  "limit": 25,
  "offset": 0,
  "has_next": false,
  "has_previous": false
}

3. Get a Single Vault Entry

GET /api/v1/vault_entry/{id}

Response (200)

json
{
  "id": "ve-abc-123",
  "key": "smtp_password",
  "kind": "SECRET",
  "value": "******",
  "description": "SMTP server password",
  "enabled": true,
  "created_at": "2026-02-28T10:00:00Z",
  "updated_at": null,
  "deleted_at": null
}

Errors

StatusCodeWhen
404VAULT.NOT_FOUNDVault entry not found

4. Update a Vault Entry

PATCH /api/v1/vault_entry/{id}

Partial update — only send the fields you want to change.

Request Body (all fields optional)

FieldTypeNotes
keystringMust be unique across non-deleted entries
kindstringSECRET or VAR. Changing to SECRET encrypts the value
valuestringRe-encrypted automatically if kind is SECRET
descriptionstring
enabledbooleanUse this to enable/disable without deleting

Response (200)

Same shape as Get a Single Vault Entry (SECRET values are masked).

Errors

StatusCodeWhen
404VAULT.NOT_FOUNDVault entry not found
409VAULT.KEY_EXISTSNew key conflicts with an existing entry

5. Delete a Vault Entry

DELETE /api/v1/vault_entry/{id}

Response (200)

json
{
  "message": "Vault entry ve-abc-123 deleted."
}

This is a soft delete (deleted_at is set). Existing configs that reference the deleted entry will fail resolution at runtime — update or remove those references first.

Errors

StatusCodeWhen
404VAULT.NOT_FOUNDVault entry not found

6. Using References in Plugin Configs

Once a vault entry is created, you can reference it in any plugin instance's config_json field. The server resolves references at runtime when the plugin is invoked — the reference string is stored as-is in the database.

Example

1. Create the vault entries:

POST /api/v1/vault_entry
{ "key": "smtp_host", "kind": "VAR", "value": "mail.example.com" }

POST /api/v1/vault_entry
{ "key": "smtp_password", "kind": "SECRET", "value": "s3cret-p4ssw0rd" }

2. Use references in the plugin instance config:

POST /api/v1/plugin_instance
{
  "plugin_definition_id": "email-sender-def",
  "name": "Production Email",
  "config_json": {
    "host": "$var:smtp_host",
    "port": 587,
    "username": "noreply@example.com",
    "password": "$secret:smtp_password",
    "use_tls": true
  }
}

3. At runtime, when the plugin is invoked, the server replaces "$var:smtp_host" with "mail.example.com" and "$secret:smtp_password" with the decrypted "s3cret-p4ssw0rd". The plugin receives:

json
{
  "host": "mail.example.com",
  "port": 587,
  "username": "noreply@example.com",
  "password": "s3cret-p4ssw0rd",
  "use_tls": true
}

Resolved values are never logged or returned via the API. The config stored in the database always contains the reference strings, not plaintext secrets.


7. Using References in Workflow Input Mappings

Vault references also work in workflow node input mappings. After JSONLogic expressions are evaluated, the resolver runs a second pass to replace any $secret:<key> or $var:<key> strings in the resolved output.

Example

A workflow node's input_mapping might look like:

json
{
  "recipient": { "var": "event.data.user_email" },
  "api_key": "$secret:sendgrid_key",
  "from_address": "$var:noreply_email"
}

After evaluation:

  • recipient is resolved from the event payload via JSONLogic
  • api_key is decrypted from the vault
  • from_address is looked up from the vault as a plaintext variable

8. Reference Syntax Rules

PatternKindExample
$secret:<key>SECRET$secret:smtp_password
$var:<key>VAR$var:api_base_url

Rules

  • Full-string match only. The entire string value must be $secret:<key> or $var:<key>. A string like "prefix $secret:key suffix" is not treated as a reference and passes through unchanged.

  • Key characters. Keys may contain letters, digits, and underscores: [a-zA-Z0-9_].

  • Nested structures. The resolver traverses dicts and lists recursively. Non-string values (numbers, booleans, null) are never affected.

  • Disabled entries. Referencing a disabled vault entry (enabled: false) raises a resolution error at runtime. The plugin invocation or workflow node will fail with error code VAULT.DISABLED.

  • Missing entries. Referencing a non-existent key raises a resolution error with code VAULT.RESOLVE_FAILED.

  • No circular references. Resolved values are not scanned again — if a vault entry's value happens to contain $secret:..., it is treated as a literal string after resolution.


9. Configuration

The vault requires vault.encryption_key in app_config.yaml to encrypt and decrypt SECRET values. This should be a Fernet-compatible key (URL-safe base64, 32 bytes).

Generating a Dedicated Key

bash
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

app_config.yaml

yaml
vault:
  encryption_key: "${VAULT_ENCRYPTION_KEY}"

The value is resolved from the environment variable at startup via the standard config store. You can reuse an existing secret (e.g. JWT_SECRET) or provide a dedicated Fernet key.

Keep this key safe. If the key is lost, all SECRET values become unrecoverable. If the key is compromised, rotate it and re-encrypt all secrets.


10. Important UI Considerations

Secret vs Variable Visual Distinction

Use clear visual indicators to differentiate the two kinds:

KindDisplay ValueBadge ColourIcon Suggestion
SECRET******red / darklock / shield
VARactual plaintextblue / greycode / variable

Value Input

  • For SECRET entries, use a password input field (masked by default with a show/hide toggle).
  • For VAR entries, use a standard text input.
  • On create, the value is required. On update, omitting the value field leaves the existing value unchanged.

Key Field

  • The key must be unique. Display a validation error if the API returns 409 VAULT.KEY_EXISTS.
  • Consider using a monospace font for the key field since it represents a code-level identifier.
  • Suggest a naming convention hint, e.g. "Use lowercase with underscores (smtp_password, api_base_url)".

Reference Helper

When editing a plugin instance config or workflow input mapping, consider providing:

  • A vault reference picker — a dropdown or autocomplete that lists available vault entries and inserts $secret:<key> or $var:<key> into the config field.
  • Fetch available entries with GET /api/v1/vault_entry?enabled=true.
  • Group by kind (SECRET / VAR) for clarity.

Enable / Disable Toggle

Use PATCH /api/v1/vault_entry/{id} with { "enabled": false } to disable an entry without deleting it. Show a warning that disabling will cause runtime failures for any configs still referencing this key.

Deletion Warning

When deleting a vault entry, warn the user that any plugin configs or workflow input mappings referencing this key will fail at runtime until the references are updated or removed.

Pagination

All list endpoints share the same pagination contract:

?limit=25&offset=0

Use has_next / has_previous booleans to enable/disable pagination controls. total gives the full count for "showing X of Y" labels.

Timestamps

All timestamps are ISO-8601 UTC. Convert to the user's local timezone for display.


Error Code Reference

CodeHTTP StatusDescription
VAULT.NOT_FOUND404Vault entry does not exist
VAULT.KEY_EXISTS409A vault entry with this key already exists
VAULT.DISABLED422Referenced vault entry is disabled
VAULT.RESOLVE_FAILED422Failed to resolve a vault reference at runtime