sondahub

sondahub / Infisical sandbox

An Infisical API mock with Universal Auth

Infisical’s API, answered by sondahub: a machine identity that logs in with Universal Auth, projects with dev, staging and prod, folders, secrets through the raw v3 and the v4 API — single and batch — with references expanded, imports, tags, versions, comments and personal overrides. Point the SDK’s host or the CLI’s API URL here.

An independent imitation for testing. Not affiliated with, or endorsed by, Infisical.

Connect

Instead of
https://app.infisical.com
Site URL
https://api.sondahub.com
Client id
9e3779b1-ccd0-8520-64cf-8f988c2ee30a
Client secret
sondahub-infisical-sandbox-client-secret
Project
9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b (Backend)
Also at
https://api.sondahub.com/sandbox/infisical
OpenAPI 3
https://api.sondahub.com/sandbox/infisical/openapi.json

Python (infisicalsdk)

from infisical_sdk import InfisicalSDKClient

client = InfisicalSDKClient(host='https://api.sondahub.com')
client.auth.universal_auth.login(client_id='9e3779b1-ccd0-8520-64cf-8f988c2ee30a', client_secret='sondahub-infisical-sandbox-client-secret')

# carry the sandbox session from each answer to the next request
http = client.api.session
def keep(response, *args, **kwargs):
    token = response.headers.get('X-Sondahub-Session')
    if token:
        http.headers['X-Sondahub-Session'] = token
http.hooks['response'].append(keep)

secrets = client.secrets.list_secrets(project_id='9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b', environment_slug='dev', secret_path='/',
                                      expand_secret_references=True)
print({s.secretKey: s.secretValue for s in secrets.secrets})

Infisical CLI

export INFISICAL_API_URL=https://api.sondahub.com/api
export INFISICAL_TOKEN=$(infisical login --method=universal-auth \
  --client-id=9e3779b1-ccd0-8520-64cf-8f988c2ee30a --client-secret=sondahub-infisical-sandbox-client-secret --silent --plain)
infisical export --projectId=9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b --env=prod --format=dotenv

Import it. In Sonda: Import → From a URL, paste the OpenAPI address. You get a folder per resource and a request per operation, with example bodies and names from the seed, so most requests work as they are. Then set the auth: Bearer: the accessToken from the login request (any token works). Any client that imports OpenAPI 3 takes the same address.

Try it here

These examples share one session: run them in order and each sees what the one before it did.
Log in with Universal Auth
curl -X POST "https://api.sondahub.com/api/v1/auth/universal-auth/login" \
  -H "Content-Type: application/json" \
  -d '{"clientId":"9e3779b1-ccd0-8520-64cf-8f988c2ee30a","clientSecret":"sondahub-infisical-sandbox-client-secret"}'
Secrets in dev, references expanded
curl "https://api.sondahub.com/api/v3/secrets/raw?workspaceId=9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b&environment=dev&secretPath=%2F&expandSecretReferences=true" \
  -H "Authorization: Bearer <accessToken from the login>"
One from a folder
curl "https://api.sondahub.com/api/v3/secrets/raw/DB_HOST?workspaceId=9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b&environment=prod&secretPath=%2Fdatabase" \
  -H "Authorization: Bearer <accessToken from the login>"
prod imports /payments
curl "https://api.sondahub.com/api/v3/secrets/raw?workspaceId=9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b&environment=prod&secretPath=%2F&include_imports=true" \
  -H "Authorization: Bearer <accessToken from the login>"
Create a secret
curl -X POST "https://api.sondahub.com/api/v3/secrets/raw/QUEUE_URL" \
  -H "Authorization: Bearer <accessToken from the login>" \
  -H "Content-Type: application/json" \
  -d '{"workspaceId":"9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b","environment":"dev","secretPath":"/","secretValue":"redis://localhost:6379/1","secretComment":"The job queue","type":"shared"}'
Update it: version 2
curl -X PATCH "https://api.sondahub.com/api/v3/secrets/raw/QUEUE_URL" \
  -H "Authorization: Bearer <accessToken from the login>" \
  -H "Content-Type: application/json" \
  -d '{"workspaceId":"9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b","environment":"dev","secretPath":"/","secretValue":"redis://cache:6379/1"}'
The folders
curl "https://api.sondahub.com/api/v2/folders?projectId=9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b&environment=prod&path=%2F" \
  -H "Authorization: Bearer <accessToken from the login>"

From the shell, keep the token yourself: curl -i shows X-Sondahub-Session; send it back with -H "X-Sondahub-Session: …". How sessions work.

The seed organization

ProjectEnvironments and folders with secrets
Backend
9e3779b1-8889-ed6a-7bdb-82e5f94b1a0b
dev /, dev /database, staging /, staging /database, prod /, prod /database, prod /payments
Web
3c6ef362-da47-3389-64e5-54bb903d3dc1
dev /, staging /, prod /

Each project has dev, staging and prod. DATABASE_URL in each environment is built from references to its /database folder; prod’s root imports /payments; LOG_LEVEL in dev has your personal override. Tags (database, payments, public) filter lists with tagSlugs.

Every value in the seed is fake and made up when the site is built. What you write is kept in your own session token and nowhere else — but this is a public playground: never send it a real secret. Not affiliated with, or endorsed by, Infisical.

What it answers

POST/api/v1/auth/universal-auth/loginAnd /api/v1/auth/token/renew, /api/v1/auth/token/revoke.
GET/api/v3/secrets/rawList (expandSecretReferences, recursive, include_imports, tagSlugs); /raw/{name}: get (version, type), POST, PATCH, DELETE; /api/v3/secrets/batch/raw.
GET/api/v4/secretsThe same with projectId: /api/v4/secrets/{name}, /api/v4/secrets/batch.
GET/api/v2/foldersAnd POST, PATCH /{id}, DELETE /{idOrName}, GET /{id}; /api/v1/folders too.
GET/api/v1/secret-importsAnd POST, DELETE /{id}.
GET/api/v1/workspaceProjects: list, get, delete; POST /api/v2/workspace; environments; tags.

Errors are Infisical’s: {"reqId", "statusCode", "message", "error"}.

Questions

Is this Infisical?

No — an independent imitation of Infisical’s API for testing, not affiliated with or endorsed by Infisical. No organization or account is involved and nothing is encrypted.

Will the Infisical SDK and CLI work against it?

The Python set-up on this page was run against the sandbox with Infisical’s Python SDK: the Universal Auth login, listing with references expanded and imports, getting by name, creating, updating, deleting, folders, and a refused login. The CLI lines use its documented API URL variable and Universal Auth login. The site URL is https://api.sondahub.com itself — the sandbox answers Infisical’s /api paths at the root.

Which credentials work?

The published machine identity — client id 9e3779b1-ccd0-8520-64cf-8f988c2ee30a, client secret sondahub-infisical-sandbox-client-secret — has its secret checked; any other UUID as a client id logs in with any secret. The access token lasts two hours and renews at /api/v1/auth/token/renew. The API then takes the token as a bearer — and any other bearer, so a request can be tried without logging in.

How are references expanded?

With expandSecretReferences=true, as Infisical does: ${KEY} from the same folder, ${env.KEY} from an environment’s root, ${env.folder.sub.KEY} from a folder. A secret import puts another folder’s secrets in imports when include_imports=true, and a get by name looks there too. A personal override replaces the shared value for you.

What is not modelled?

The other auth methods (AWS, GCP, Azure, Kubernetes, OIDC, LDAP), dynamic secrets, rotation, the KMS API, approvals, point-in-time recovery, secret sharing and the end-to-end-encrypted (non-raw) secret endpoints. A secret keeps its last 10 values.