Skip to content

Commit 541f571

Browse files
committed
cleanup + additional testing
1 parent 1f13c3a commit 541f571

213 files changed

Lines changed: 6158 additions & 5444 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Code Generation
66

7-
Most of the SDK is **auto-generated** by `oagen` (an internal OpenAPI code generator). Generated files begin with `# This file is auto-generated by oagen. Do not edit.` Hand-maintained code is fenced with `@oagen-ignore-start` / `@oagen-ignore-end` markers (e.g., `session.py`, `passwordless.py`, `vault.py`).
7+
Most of the SDK is **auto-generated** by `oagen` (an internal OpenAPI code generator). Generated files begin with `# This file is auto-generated by oagen. Do not edit.` Hand-maintained code is fenced with `@oagen-ignore-start` / `@oagen-ignore-end` markers or marked with `# @oagen-ignore-file` (e.g., `session.py`, `passwordless.py`, `vault.py`, `public_client.py`, `pkce.py`, `actions.py`).
88

99
## Development Commands
1010

@@ -73,11 +73,9 @@ bash scripts/build_and_upload_dist.sh # Build and upload to PyPI
7373

7474
The SDK provides both synchronous and asynchronous clients:
7575

76-
- `WorkOS` (sync) and `AsyncWorkOS` (async) are the main entry points (exported from `workos/__init__.py`)
77-
- Both inherit from `_BaseWorkOS` (in `workos/_client.py`) which handles configuration, HTTP transport, retry logic, and error mapping
76+
- `WorkOSClient` (sync) and `AsyncWorkOSClient` (async) are the main entry points (exported from `workos/__init__.py`)
77+
- Both inherit from `_BaseWorkOSClient` (in `workos/_client.py`) which handles configuration, HTTP transport, retry logic, and error mapping
7878
- Each feature area (SSO, Organizations, etc.) is exposed as a `@functools.cached_property` on the client for lazy loading
79-
- Complex feature areas use namespace classes (e.g., `UserManagementNamespace`, `OrganizationsNamespace`) to group sub-resources
80-
- Backward-compatible aliases exist: `WorkOSClient = WorkOS`, `AsyncWorkOSClient = AsyncWorkOS`
8179
- HTTP transport uses `httpx` directly; there is no separate HTTP client abstraction layer
8280

8381
### Module Structure
@@ -93,7 +91,7 @@ src/workos/{module_name}/
9391
{model}.py # Individual dataclass model files
9492
```
9593

96-
Resource classes take a `WorkOS` or `AsyncWorkOS` client reference and call `self._client.request()` or `self._client.request_page()` for paginated endpoints.
94+
Resource classes take a `WorkOSClient` or `AsyncWorkOSClient` client reference and call `self._client.request()` or `self._client.request_page()` for paginated endpoints.
9795

9896
### Type System
9997

@@ -108,13 +106,12 @@ Resource classes take a `WorkOS` or `AsyncWorkOS` client reference and call `sel
108106
- `SyncPage[T]` and `AsyncPage[T]` dataclasses in `workos/_pagination.py` represent paginated results
109107
- Cursor-based: `before`/`after` properties, `has_more()` check
110108
- `auto_paging_iter()` transparently fetches subsequent pages
111-
- Backward-compatible alias: `WorkOSListResource = SyncPage`
112109

113110
### Error Handling
114111

115112
All exceptions live in `workos/_errors.py` and inherit from `WorkOSError`:
116113

117-
- `BadRequestError` (400), `AuthenticationError` (401), `ForbiddenError` (403), `NotFoundError` (404), `ConflictError` (409), `UnprocessableEntityError` (422), `RateLimitExceededError` (429), `ServerError` (5xx)
114+
- `BadRequestError` (400), `AuthenticationError` (401), `AuthorizationError` (403), `NotFoundError` (404), `ConflictError` (409), `UnprocessableEntityError` (422), `RateLimitExceededError` (429), `ServerError` (5xx)
118115
- `ConfigurationError`, `WorkOSConnectionError`, `WorkOSTimeoutError` for non-HTTP errors
119116
- `STATUS_CODE_TO_ERROR` dict maps status codes to exception classes
120117

@@ -128,6 +125,6 @@ All exceptions live in `workos/_errors.py` and inherit from `WorkOSError`:
128125

129126
### Configuration
130127

131-
- Environment variable support: `WORKOS_API_KEY`, `WORKOS_CLIENT_ID`
128+
- Environment variable support: `WORKOS_API_KEY`, `WORKOS_CLIENT_ID`, `WORKOS_BASE_URL`, `WORKOS_REQUEST_TIMEOUT`
132129
- Retry logic: exponential backoff with jitter, retries on 429/5xx, respects `Retry-After` headers
133-
- Default timeout: 30 seconds
130+
- Default timeout: 60 seconds

README.md

Lines changed: 126 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,68 +3,166 @@
33
![PyPI](https://img.shields.io/pypi/v/workos)
44
[![Build Status](https://workos.semaphoreci.com/badges/workos-python/branches/main.svg?style=shields&key=9e4cb5bb-86a4-4938-9ec2-fc9f9fc512be)](https://workos.semaphoreci.com/projects/workos-python)
55

6-
The WorkOS library for Python provides convenient access to the WorkOS API from applications written in Python, [hosted on PyPi](https://pypi.org/project/workos/)
6+
The WorkOS library for Python provides convenient access to the WorkOS API from applications written in Python, [hosted on PyPI](https://pypi.org/project/workos/).
77

88
## Documentation
99

1010
See the [API Reference](https://workos.com/docs/reference/client-libraries) for Python usage examples.
1111

1212
## Installation
1313

14-
To install from PyPi, run the following:
15-
16-
```
14+
```bash
1715
pip install workos
1816
```
1917

20-
To install from source, clone the repo and run the following:
18+
## Quick Start
2119

22-
```
23-
python -m pip install .
20+
```python
21+
from workos import WorkOSClient
22+
23+
client = WorkOSClient(api_key="sk_1234", client_id="client_1234")
24+
25+
# List organizations
26+
page = client.organizations.list_organizations()
27+
for org in page.auto_paging_iter():
28+
print(org.name)
29+
30+
# Create an organization
31+
org = client.organizations.create_organizations(name="Acme Corp")
32+
print(org.id)
2433
```
2534

26-
## Configuration
35+
### Async Client
2736

28-
The package will need to be configured with your [api key and client ID](https://dashboard.workos.com/api-keys).
37+
Every method has an identical async counterpart:
2938

3039
```python
31-
from workos import WorkOSClient
40+
from workos import AsyncWorkOSClient
3241

33-
workos_client = WorkOSClient(
34-
api_key="sk_1234", client_id="client_1234"
35-
)
42+
async_client = AsyncWorkOSClient(api_key="sk_1234", client_id="client_1234")
43+
44+
page = await async_client.organizations.list_organizations()
45+
async for org in page.auto_paging_iter():
46+
print(org.name)
3647
```
3748

38-
The SDK also provides asyncio support for some SDK methods, via the async client:
49+
### Environment Variables
50+
51+
The client reads credentials from the environment when not passed explicitly:
52+
53+
| Variable | Description |
54+
|----------|-------------|
55+
| `WORKOS_API_KEY` | WorkOS API key |
56+
| `WORKOS_CLIENT_ID` | WorkOS client ID |
57+
| `WORKOS_BASE_URL` | Override the API base URL (defaults to `https://api.workos.com/`) |
58+
| `WORKOS_REQUEST_TIMEOUT` | HTTP timeout in seconds (defaults to `60`) |
59+
60+
## Available Resources
61+
62+
The client exposes the full WorkOS API through typed namespace properties:
63+
64+
| Property | Description |
65+
|----------|-------------|
66+
| `client.sso` | Single Sign-On connections and authorization |
67+
| `client.organizations` | Organization management |
68+
| `client.user_management` | Users, identities, auth methods, invitations |
69+
| `client.directory_sync` | Directory connections and directory users/groups |
70+
| `client.admin_portal` | Admin Portal link generation |
71+
| `client.audit_logs` | Audit log events, exports, and schemas |
72+
| `client.authorization` | Fine-Grained Authorization (FGA) resources, roles, permissions, and checks |
73+
| `client.webhooks` | Webhook event verification |
74+
| `client.feature_flags` | Feature flag evaluation |
75+
| `client.api_keys` | Organization API key management |
76+
| `client.connect` | OAuth application management |
77+
| `client.widgets` | Widget session tokens |
78+
| `client.multi_factor_auth` | MFA enrollment and verification (also available as `client.mfa`) |
79+
| `client.pipes` | Data Integrations |
80+
| `client.radar` | Radar risk scoring |
81+
| `client.passwordless` | Passwordless authentication sessions |
82+
| `client.vault` | Encrypted data vault |
83+
84+
## Pagination
85+
86+
Paginated endpoints return `SyncPage[T]` (or `AsyncPage[T]`) with built-in auto-pagination:
3987

4088
```python
41-
from workos import AsyncWorkOSClient
89+
# Iterate through all pages automatically
90+
for user in client.user_management.list_users().auto_paging_iter():
91+
print(user.email)
92+
93+
# Or work with a single page
94+
page = client.user_management.list_users(limit=10)
95+
print(page.data) # List of items on this page
96+
print(page.has_more()) # Whether more pages exist
97+
print(page.after) # Cursor for the next page
98+
```
99+
100+
## Error Handling
101+
102+
All API errors map to typed exception classes with rich context:
103+
104+
```python
105+
from workos._errors import NotFoundError, RateLimitExceededError
106+
107+
try:
108+
client.organizations.get_organization("org_nonexistent")
109+
except NotFoundError as e:
110+
print(f"Not found: {e.message}")
111+
print(f"Request ID: {e.request_id}")
112+
except RateLimitExceededError as e:
113+
print(f"Retry after: {e.retry_after} seconds")
114+
```
115+
116+
| Exception | Status Code |
117+
|-----------|-------------|
118+
| `BadRequestError` | 400 |
119+
| `AuthenticationError` | 401 |
120+
| `AuthorizationError` | 403 |
121+
| `NotFoundError` | 404 |
122+
| `ConflictError` | 409 |
123+
| `UnprocessableEntityError` | 422 |
124+
| `RateLimitExceededError` | 429 |
125+
| `ServerError` | 5xx |
42126

43-
async_workos_client = AsyncWorkOSClient(
44-
api_key="sk_1234", client_id="client_1234"
127+
## Per-Request Options
128+
129+
Every method accepts `request_options` for per-call overrides:
130+
131+
```python
132+
result = client.organizations.list_organizations(
133+
request_options={
134+
"timeout": 10,
135+
"max_retries": 5,
136+
"extra_headers": {"X-Custom": "value"},
137+
"idempotency_key": "my-key",
138+
"base_url": "https://staging.workos.com/",
139+
}
45140
)
46141
```
47142

143+
## Type Safety
144+
145+
This SDK ships with full type annotations (`py.typed` / PEP 561) and works with mypy, pyright, and IDE autocompletion out of the box. All models are `@dataclass(slots=True)` classes with `from_dict()` / `to_dict()` for serialization.
146+
48147
## SDK Versioning
49148

50-
For our SDKs WorkOS follows a Semantic Versioning ([SemVer](https://semver.org/)) process where all releases will have a version X.Y.Z (like 1.0.0) pattern wherein Z would be a bug fix (e.g., 1.0.1), Y would be a minor release (1.1.0) and X would be a major release (2.0.0). We permit any breaking changes to only be released in major versions and strongly recommend reading changelogs before making any major version upgrades.
149+
WorkOS follows [Semantic Versioning](https://semver.org/). Breaking changes are only released in major versions. We strongly recommend reading changelogs before making major version upgrades.
51150

52151
## Beta Releases
53152

54-
WorkOS has features in Beta that can be accessed via Beta releases. We would love for you to try these
55-
and share feedback with us before these features reach general availability (GA). To install a Beta version,
56-
please follow the [installation steps](#installation) above using the Beta release version.
57-
58-
> Note: there can be breaking changes between Beta versions. Therefore, we recommend pinning the package version to a
59-
> specific version. This way you can install the same version each time without breaking changes unless you are
60-
> intentionally looking for the latest Beta version.
153+
WorkOS has features in Beta that can be accessed via Beta releases. We would love for you to try these and share feedback with us before these features reach general availability (GA). To install a Beta version, please follow the [installation steps](#installation) above using the Beta release version.
61154

62-
We highly recommend keeping an eye on when the Beta feature you are interested in goes from Beta to stable so that you
63-
can move to using the stable version.
155+
> **Note:** there can be breaking changes between Beta versions. We recommend pinning the package version to a specific version.
64156
65157
## More Information
66158

67159
- [Single Sign-On Guide](https://workos.com/docs/sso/guide)
160+
- [User Management Guide](https://workos.com/docs/user-management)
161+
- [AuthKit Guide](https://workos.com/docs/authkit)
68162
- [Directory Sync Guide](https://workos.com/docs/directory-sync/guide)
69163
- [Admin Portal Guide](https://workos.com/docs/admin-portal/guide)
70-
- [Magic Link Guide](https://workos.com/docs/magic-link/guide)
164+
- [Audit Logs Guide](https://workos.com/docs/audit-logs)
165+
- [Authorization (FGA) Guide](https://workos.com/docs/fga)
166+
- [Feature Flags Guide](https://workos.com/docs/feature-flags)
167+
- [Webhooks Guide](https://workos.com/docs/webhooks)
168+
- [Radar Guide](https://workos.com/docs/radar)

src/workos/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from ._client import AsyncWorkOSClient, WorkOSClient
66
from ._errors import WorkOSError
77
from ._pagination import AsyncPage, ListMetadata, SyncPage
8+
from .public_client import create_public_client
89
from ._types import RequestOptions
910

1011
__all__ = [
@@ -15,4 +16,5 @@
1516
"AsyncPage",
1617
"ListMetadata",
1718
"RequestOptions",
19+
"create_public_client",
1820
]

0 commit comments

Comments
 (0)