Getting started

Changelog

Version history for envless-sdk, the Python SDK.

Version history for envless-sdk, the Python client for the Envless API, published on PyPI. Pin it for the latest coverage, security patches and type fixes. When a newer version is out, the client says so once on a terminal, with a link to this page.

The TypeScript SDK, @goenvless/sdk, has its own changelog. The two cover the same API, and a change to one lands in the other.

Unreleased

Next release

Each list method takes only the options its route reads. The keyword arguments now match the TypeScript option types route by route, so an option the API ignored is no longer accepted and a filter it honors is no longer missing. Passing a removed keyword raises TypeError instead of being sent and ignored.

  • members.list, list_all and iterate gain role_id=, and roles.list, list_all and iterate gain sort_by= ('name', 'updated' or 'created')
  • Removed where the route ignores them: order= and product= on members, invites and roles, search= and order= on variables, versions, version entries and variable history, product= on products, keys and webhooks, and everything but limit= and offset= on workspaces and products.access
  • variables.get_by_id, update_by_id, delete_by_id, versions.get and versions.rollback no longer take product= and stop sending ?product=, and neither does rotate_workspace_passphrase when it updates variables
  • VariableInput and VariablePatch accept isSecret, and ApplyUpdateEntry accepts name, which renames the variable inside variables.apply

Rotation reports every default it cannot move. rotate_workspace_passphrase now lists in failures any version entry whose value is empty or plaintext while its defaultValue is ciphertext, with scope set to 'versionEntry' and field to 'defaultValue'. The API only rewrites version entries that carry a ciphertext value, so such a default stayed sealed under the old passphrase while the run looked clean. Keep the old passphrase until those entries are dealt with.

Initial release. The Python twin of the TypeScript SDK, covering 100% of the public HTTP API: all 113 methods across 13 namespaces, under their TypeScript names in snake_case. A parity check replays every method through both Python clients against the requests the TypeScript SDK records, with no options and with every option set, and fails the build on any difference in the request, the retries, the errors or the result.

Clients

  • Envless for synchronous code and AsyncEnvless for asyncio and trio, with the same methods, arguments and results, generated from one source
  • from envless import envless is a ready made client built from ENVLESS_TOKEN and ENVLESS_API_ENDPOINT the first time it is touched, and init(...) configures it once at startup. get_client() returns it and reset_client() drops it
  • create_client is Envless under the TypeScript name. Unlike TypeScript's new Envless(), both Python constructors read the environment for whatever you leave out
  • Namespaces: me, workspace (with workspace.domain), workspaces, products (with products.access), projects, environments, variables, versions, members, invites, roles, keys, webhooks
  • Request bodies and results are plain dicts keyed by the API's own field names, and every one has a TypedDict in envless.types. The package ships py.typed
  • Options are keyword arguments: product=, limit=, offset=, search=, order=, status=, reattempt=, and timeout= on every method
  • raw.request(path, method=..., query=..., body=...) reaches an endpoint no method wraps yet, with the client's key, base URL, timeout and retries
  • Bring your own httpx.Client or httpx.AsyncClient as http_client for a proxy, custom TLS or httpx.MockTransport in tests. Redirects are followed whatever it says

Pagination

  • Every collection has list for one page, list_all for everything, and iterate for a lazy stream, async for on AsyncEnvless
  • Secondary collections get their own trio: products.list_projects, products.access.list, variables.list_history, versions.list_entries, webhooks.list_deliveries, each with list_all_* and iterate_* forms
  • The walk ends on hasMore being False or an empty page, and advances by the items actually received

Errors

  • EnvlessApiError carries the stable code plus status, message, resource, field, request_id and retry_after_seconds, with properties for the common branches: is_auth, is_scope_missing, is_validation, needs_upgrade, is_not_found, is_conflict, is_rate_limited
  • EnvlessNetworkError for transport failures, with is_timeout when the deadline passed. DecryptionError and WebhookVerificationError for the crypto and webhook helpers. All of them inherit EnvlessError, and all of them pickle
  • GET, HEAD, PUT and DELETE are retried on 408, 429, 500, 502, 503 and 504 with exponential backoff capped at 30 seconds, honouring Retry-After. POST and PATCH are never retried
  • timeout is a hard deadline for each attempt, the response body included, on both clients. 0 turns it off
  • A variable name is checked before anything is sent, and an unusable one raises the same EnvlessApiError the API would, with request_id set to None

Encryption

  • encrypt_value and decrypt_value, byte-for-byte compatible with the TypeScript SDK, the CLI, the dashboard and @goenvless/env: AES-256-GCM under a PBKDF2-SHA-256 key with 200,000 iterations and the workspace salt. v1: and v2:<iterations>: envelopes both decrypt
  • derive_workspace_key and import_workspace_key return a WorkspaceKey that never prints its bytes, for encrypt_with_key and decrypt_with_key across a batch
  • is_ciphertext, passphrase_strength, variable_name_validation and ENCRYPTION_PARAMETERS
  • rotate_workspace_passphrase(client=..., ...) re-encrypts an environment's live variables and its version history, with either client

Webhooks

  • verify_webhook_signature(payload=..., headers=..., secret=...) checks the HMAC-SHA256 signature in constant time and the timestamp drift, then returns the parsed event. It takes the raw body as bytes or str and headers from any framework, matched case-insensitively

Runtime

  • Python 3.10 or newer. Depends on httpx, anyio, cryptography and typing-extensions
  • Every request carries User-Agent: envless-sdk-python/0.0.1