Metadata-Version: 2.4
Name: ordan
Version: 0.1.0
Summary: Official Python client for the ORDan API — communications infrastructure for autonomous AI agents
Author: Neuromorph Systems, LLC
Project-URL: Homepage, https://ordan.io
Project-URL: Documentation, https://ordan.io/docs/
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# ordan

The Python client for [ORDan](https://ordan.io), communications infrastructure for autonomous AI agents.

```bash
pip install ordan
```

```python
import os
import ordan

ordan.api_key = os.environ["ORDAN_API_KEY"]

agent = ordan.agents.create(name="Executive Assistant")
line = ordan.lines.create(agent=agent.id, country="US")

call = ordan.calls.create(
    agent=agent.id,
    to="+12125550123",
    objective="Move Tuesday's appointment to Friday afternoon.",
)
# call.status == "authorized"; call.line == "+12125550148"; call.policy == "default_policy_v1"
```

Python 3.9+, standard library only.

API objects are dicts that also read as attributes: `call.status` and `call["status"]` return the same value. Lists have `.data` and `.next_cursor`.

## Configuration

Configure the module-level client:

- `ordan.api_key` falls back to `ORDAN_API_KEY`. Without one, only the public `prices.retrieve()` works; every other call raises `missing_api_key`.
- `ordan.base_url` falls back to `ORDAN_API_URL`, then `https://api.ordan.io`.
- `ordan.max_retries` defaults to 2.
- `ordan.timeout` defaults to 60 seconds.

To use several credentials at once, create explicit clients:

```python
from ordan import Ordan

backend = Ordan(api_key="ordan_sk_live_…")       # a project key acts for its agents
assistant = Ordan(api_key="ordan_sk_agent_…")    # an agent credential acts as that agent
```

Either way, each action passes the agent's grant, its pinned policy and its budget.

## Approvals and refusals

```python
try:
    call = ordan.calls.create(agent=agent.id, to=to, objective=objective)
except ordan.ApprovalRequiredError as err:
    # The owner approves err.approval_request (apr_…) in the console, then:
    call = ordan.calls.create(agent=agent.id, to=to, objective=objective, approval=err.approval_request)
```

Every error is an `ordan.OrdanError` carrying `status`, `code`, `message` and `details`. The subclasses are:

- `ApprovalRequiredError`
- `PolicyViolationError`
- `SpendLimitError`: refused, not billed
- `PermissionDeniedError`
- `ValidationError`
- `AuthenticationError`
- `NotFoundError`
- `ConflictError`
- `RateLimitError`
- `APIError`
- `APIConnectionError`

## Retries and idempotency

Every POST sends an `Idempotency-Key`, so a retry can never place a second call or send a second text.

- The same key is reused for all retries of that request.
- Network errors, 408, 429 and 5xx responses are retried with backoff, and `Retry-After` is honored.
- Other 4xx responses are never retried.

To tie a request to your own operation, pass `idempotency_key="…"` to any `create`.

## Resources

- `agents`: `create`, `retrieve`, `list`
- `lines`: `create`, `retrieve`, `list`, `release`
- `calls`: `create`, `retrieve`, `list`, `hangup`, `answer`, `transfer`
- `messages`: `create`, `retrieve`, `list`. `list(with_="+1…")` returns a conversation.
- `usage`: `retrieve`, `ledger`
- `events`: `list`
- `policy`: `check`

`client.request(method, path, query=…, body=…)` reaches endpoints the SDK doesn't wrap yet.

## Tests

```bash
python3 -m unittest discover -s sdks/python/tests
```

`tests/test_live.py` runs the sample above against a real API when `ORDAN_TEST_API_URL` and `ORDAN_TEST_API_KEY` are set.

## License

Copyright Neuromorph Systems, LLC. All rights reserved. Proprietary software; see `LICENSE`.
