Typed clients with nothing hidden behind them
TypeScript with zero dependencies, Python with sync and async clients, Ruby with RBS types, PHP with PHPStan and Psalm types, and 113 methods in each covering all 80 API operations, enforced by parity checks in CI.
What ships in the package
Typed TypeScript, Python, Ruby and PHP clients for the Envless public API, with thirteen resource namespaces and the dashboard's encryption primitives, so you can encrypt a value locally before writing it.
Full definition
The @goenvless/sdk package is a typed TypeScript client for the Envless public API. It exposes thirteen resource namespaces, three pagination shapes on every collection, two error classes you can branch on without parsing messages, and the same client-side encryption primitives the dashboard uses, so you can encrypt a value locally before writing it through the API. It is a separate concern from @goenvless/env, the runtime package that reads variables into a running application: the SDK manages Envless, the runtime consumes it. Its Python twin, envless-sdk on PyPI, has the same 113 methods under snake_case names, with a synchronous and an asynchronous client. Its Ruby twin, envless-sdk on RubyGems, has them too, with RBS types and no dependencies, and so does its PHP twin, envless/sdk on Packagist, with PHPStan and Psalm types and no Composer dependencies. All of them send the same requests and write the same ciphertext.
SDK overview
Installation, the client, and how the package is laid out.
Errors
Every error code, what raises it, and which ones are worth retrying.
Python SDK
envless-sdk on PyPI: the same methods for Python, sync and async.
Ruby SDK
envless-sdk on RubyGems: the same methods for Ruby, typed with RBS.
PHP SDK
envless/sdk on Packagist: the same methods for PHP, typed for PHPStan and Psalm.
Encryption helpers
encryptValue, decryptValue, key derivation and passphrase rotation.
Webhook verification
Standard Webhooks headers, tolerance, and the raw-body requirement.
CLI, runtime and SDK
Which package to reach for, and why they are deliberately separate.
Methods covering API operations
113 / 80Every documented operation has a method with a matching operationId and declared scope. A sdk:parity script diffs the manifest against the OpenAPI document and exits non-zero on any drift, so the coverage claim is enforced rather than asserted.
Runtime dependencies
0The TypeScript package has no dependencies key at all. The built bundle imports nothing external and touches no Node built-ins, using only fetch, crypto.subtle and base64 helpers. Dual ESM and CommonJS with separate type declarations, sideEffects false, Node 20 or newer.
Resource namespaces
13me, workspace, workspaces, products, projects, environments, variables, versions, members, invites, roles, keys and webhooks. Each collection ships list, iterate and listAll.
The same client on PyPI
Pythonenvless-sdk has every method under its snake_case name, with Envless for synchronous code and AsyncEnvless for asyncio and trio. A parity check replays all 113 methods through both Python clients against the requests the TypeScript SDK records and fails on any difference.
The same client on RubyGems
Rubyenvless-sdk has every method under its snake_case name, RBS signatures for every request and response, and no runtime dependencies. Its own parity check replays all 113 methods against the requests the TypeScript SDK records and fails on any difference.
The same client on Packagist
PHPenvless/sdk has every method under its TypeScript name, a PHPStan and Psalm array shape for every request and response, and no Composer dependencies. Its own parity check replays all 113 methods against the requests the TypeScript SDK records and fails on any difference.
The only retried statuses
408, 429, 5xxRetries fire on GET, HEAD, PUT and DELETE only, with exponential backoff of 2^attempt times 250ms capped at 30 seconds. POST and PATCH are never retried, so a create cannot be duplicated by a timeout.
Default webhook tolerance
300sverifyWebhookSignature implements Standard Webhooks: HMAC-SHA256 over id, timestamp and the raw payload, compared in constant time, accepting the multi-signature header format.
The SDKs FAQ
The SDK manages Envless: it creates projects, writes variables, rotates keys and reads audit data through the public API with an API key. The env package consumes Envless: it loads the variables for one project and environment into a running application and exposes them as a typed, read-only proxy. An application typically uses env; a script, an internal tool or an integration uses the SDK.
The TypeScript SDK refuses to construct in one unless you pass dangerouslyAllowBrowser, and the flag is named that way on purpose. Beyond the obvious problem of shipping an API key to users, the API only echoes the dashboard origin in its CORS headers, so a browser request would be blocked anyway. Use the SDK from a server.
Because a timeout does not tell you whether the write landed. Retrying a create after a request that may have succeeded is how you end up with two of something. GET, HEAD, PUT and DELETE are idempotent, so they retry on 408, 429 and the 5xx family with exponential backoff; anything else is handed to you to decide about.
No, and that is intentional: automatic encryption would mean the SDK holding your passphrase for the lifetime of the client. It exposes encryptValue and decryptValue, encrypt_value and decrypt_value in Python and Ruby, and Envless::encryptValue and Envless::decryptValue in PHP, so encryption is an explicit step you control, and the API refuses any value that is not already an envelope, so a forgotten call fails loudly with variable.ciphertext_invalid rather than silently storing plaintext.
Use variables.apply with a baseline. You send the id, name and updatedAt of every variable you based your change on; the server takes an advisory lock on the environment, recomputes drift, and rejects the whole call with 409 variable.baseline_drifted naming what changed. That is compare-and-set for a whole environment, and it is what the dashboard raw editor uses.
TypeScript, Python, Ruby and PHP ship today: @goenvless/sdk on npm, envless-sdk on PyPI with the same 113 methods, a synchronous client and an asynchronous one, envless-sdk on RubyGems with the same methods and RBS types, and envless/sdk on Packagist with the same methods and PHPStan and Psalm types. Underneath is a plain REST API: bearer token, JSON, standard status codes, and an OpenAPI document you can generate a client from in any other language. The encryption is the part worth porting carefully, and the encryption reference page documents the exact parameters so an implementation in another language interoperates.
A key carries a map over eleven resources at three levels: none, read or write. Each route declares what it needs and the check is a rank comparison, so a miss returns 403 auth.scope_missing naming the exact scope required. GET /me is the only public route with no scope requirement. Workspace RBAC is a separate, finer catalogue of 45 named permissions that governs people rather than keys.
