Metadata-Version: 2.4
Name: intent-api
Version: 0.1.0
Summary: A constraint-driven API framework for Python. One endpoint. Typed intents. Zero boilerplate.
Author: Chris Bora
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://intentapi.dev
Project-URL: Documentation, https://intentapi.dev/docs
Project-URL: Repository, https://github.com/chrisboraai/intent-api
Keywords: api,fastapi,intent,cqrs,framework
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.100.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: httpx>=0.24.0; extra == "dev"
Requires-Dist: uvicorn>=0.20.0; extra == "dev"
Dynamic: license-file

# Intent API

**One endpoint. Typed intents. Zero boilerplate.**

Intent API is a constraint-driven API framework for Python. Instead of writing dozens of REST endpoints, you declare **intents** — structured requests that describe what the caller wants to do. The framework dispatches them to the right handler automatically.

```
POST /api/intent
{
  "model": "Todo",
  "action": "create",
  "payload": { "title": "Ship Intent API", "done": false },
  "context": { "type": "user", "team_id": "abc-123" }
}
```

## Install

```bash
pip install intent-api
```

## Quickstart

```python
from fastapi import FastAPI
from intent_api import IntentRouter, IntentService, MutationResponse

app = FastAPI()

# 1. Define a service
class TodoService(IntentService):
    async def create(self, *, db, user, context, payload):
        # Your create logic here
        return MutationResponse(success=True, id="1", message="Todo created")

    async def list(self, *, db, user, context, skip, limit):
        return {"items": [], "total": 0}

# 2. Create router and register services
router = IntentRouter()
router.register("Todo", TodoService())

# 3. Build and include the FastAPI router
app.include_router(router.build(
    get_user=my_auth_dependency,  # Your auth function
    get_db=my_db_dependency,      # Your DB session function
))
```

That's it. One endpoint handles all CRUD + custom commands for every model.

## Core Concepts

### IntentRequest

Every API call is an `IntentRequest`:

| Field | Type | Description |
|-------|------|-------------|
| `model` | `str` | Target resource (e.g., `"Todo"`, `"User"`) |
| `action` | `str` | `"create"`, `"read"`, `"update"`, `"delete"`, `"list"`, `"custom"` |
| `id` | `any?` | Resource ID for read/update/delete |
| `payload` | `dict?` | Data for create/update/custom |
| `command` | `str?` | Named command when action is `"custom"` |
| `context` | `IntentContext?` | Caller context (role, team, org) |
| `skip` | `int?` | Pagination offset (default: 0) |
| `limit` | `int?` | Pagination limit (default: 10) |

### IntentContext

Context tells the backend **who** is calling and **what scope** they're in:

```python
{
    "type": "member",          # Role/surface type
    "team_id": "uuid-123",     # Team scope
    "organization_id": null,   # Org scope (optional)
}
```

### IntentService

Subclass `IntentService` for each model. Override the methods you need:

```python
class UserService(IntentService):
    async def create(self, *, db, user, context, payload):
        ...

    async def read(self, *, db, user, id, context):
        ...

    async def update(self, *, db, user, id, context, payload):
        ...

    async def delete(self, *, db, user, id, context):
        ...

    async def list(self, *, db, user, context, skip, limit):
        ...

    async def custom_action(self, *, db, user, context, command, id, payload):
        if command == "archive":
            return await self._archive(db=db, id=id)
        raise ValueError(f"Unknown command: {command}")
```

### Custom Commands

Custom commands let you go beyond CRUD:

```json
{
    "model": "Report",
    "action": "custom",
    "command": "export_csv",
    "payload": { "date_from": "2024-01-01", "date_to": "2024-12-31" }
}
```

## Multiple Surfaces

Intent API supports multiple access levels from the same registry:

```python
router = IntentRouter()
router.register("Todo", TodoService())
router.register("User", UserService())

# Standard: authenticated users
app.include_router(router.build(
    get_user=my_auth_dependency,
    get_db=get_db,
))

# Admin: requires additional authorization
app.include_router(router.build_admin(
    get_user=my_auth_dependency,
    get_db=get_db,
    authorize=lambda user, ctx: user.email.endswith("@mycompany.com"),
))

# Guest: unauthenticated, restricted actions
app.include_router(router.build_guest(
    get_db=get_db,
))
```

### Guest Access Control

Mark services as guest-accessible:

```python
class PublicFeedService(IntentService):
    is_guest_allowed = True
    allowed_guest_actions = ["list", "read"]

    async def list(self, *, db, user, context, skip, limit):
        # user will be None for guest requests
        return {"items": [...], "total": 10}
```

## Auth Integration

Intent API is auth-agnostic. Provide your own `get_user` dependency:

```python
# Example with Clerk
async def get_user(credentials, context, db):
    clerk_user_id = verify_clerk_token(credentials.credentials)
    return db.query(User).filter(User.clerk_id == clerk_user_id).first()

# Example with Auth0
async def get_user(credentials, context, db):
    payload = decode_auth0_token(credentials.credentials)
    return db.query(User).filter(User.auth0_id == payload["sub"]).first()

# Wire it up
app.include_router(router.build(get_user=get_user, get_db=get_db))
```

## Why Intent API?

| Traditional REST | Intent API |
|-----------------|------------|
| `GET /users`, `POST /users`, `GET /users/:id`, `PUT /users/:id`, `DELETE /users/:id`, `POST /users/:id/archive`, `GET /reports/export` ... | `POST /api/intent` |
| 40+ endpoints to maintain | 1 endpoint, N services |
| Auth middleware on every route | Auth once at the intent surface |
| No standard request format | Every request is an `IntentRequest` |
| Hard to audit ("which endpoints access sensitive data?") | One place to log all access |

## License

Copyright 2026 Chris Bora. All rights reserved.

Free for personal and evaluation use. Commercial use requires a license.
See [intentapi.dev/pricing](https://intentapi.dev/pricing) for details.
