Skip to content

Repository files navigation

Arrest



Arrest is a type-safe HTTP client for Python built on httpx and Pydantic. Define your REST APIs declaratively — routes, request/response models, retries, and error handling in one place — and get full static analysis, autocomplete, and runtime validation for every call.

Features

  • Type-safe — Pydantic models, dataclasses, dicts, lists, and XML models for request and response validation
  • Declarative — Services, resources, and handlers keep your API surface organized
  • JSON, Form, Multipart, and XMLapplication/json, application/x-www-form-urlencoded, multipart/form-data, and application/xml content types
  • Retries — Built-in exponential backoff via tenacity, or transport-level retries via httpx
  • Exception handling — Custom hooks per exception type, clean RequestError for transport failures
  • OpenAPI codegen — Generate Arrest services and Pydantic models from an OpenAPI spec
  • H() helper — IDE-friendly handler definitions with keyword-argument autocomplete
  • Unified Response[T] — One response type for all HTTP status codes with is_success, is_client_error, etc.
  • pydantic-ai toolset — Expose a Service as agent-callable tools via ArrestToolset

Installation

uv

uv add arrest

pip

pip install arrest

OpenAPI support (optional)

uv add 'arrest[openapi]'

pydantic-ai toolset (optional)

uv add arrest --extra ai

Quickstart

from arrest import H, Resource, Service, GET, POST

user = Resource(
    route="/users",
    handlers=[
        H(GET, "/"),
        H(GET, "/{user_id}"),
        H(POST, "/", request=NewUserRequest, response=UserResponse),
    ],
)

svc = Service(
    name="api",
    url="https://api.example.com/v1",
    resources=[user],
)

# GET /users
resp = await svc.users.get("/")
if resp.is_success:
    print(resp.data)

# POST /users with type-safe request body
resp = await svc.users.post("/", request=NewUserRequest(name="Alice", email="a@b.com"))

XML, Form, and File uploads

from pydantic_xml import BaseXmlModel, element
from arrest.params import Form, File
from arrest.types import UploadFile

# XML request/response
class XmlPayload(BaseXmlModel, tag="payload"):
    key: str = element()
    value: str = element()

# Form-encoded
class Login(BaseModel):
    username: str = Form(...)
    password: str = Form(...)

# Multipart file upload
class Profile(BaseModel):
    name: str = Form(...)
    avatar: UploadFile = File(...)

OpenAPI codegen

arrest --url https://petstore3.swagger.io/api/v3/openapi.json -o ./generated

Generates models.py, resources.py, and services.py from any OpenAPI spec.


pydantic-ai toolset

Expose a Service as agent-callable tools by opting handlers in with tool_meta:

from arrest.ai.meta import ToolMeta
from arrest.ai.toolset import ArrestToolset
from pydantic_ai import Agent

users = Resource(
    name="users",
    route="/users",
    handlers=[
        H(GET, "/{user_id}", None, User, tool_meta=ToolMeta(name="get_user_by_id")),
    ],
)
service = Service(name="example", url="http://localhost:8080/api", resources=[users])

toolset = ArrestToolset(service)
agent = Agent(model="anthropic:claude-haiku-4-5", toolsets=[toolset])

result = await agent.run("Look up user abc123.")  # pydantic-ai enters/exits the toolset for you

See the pydantic-ai toolset docs for include/exclude filtering, retry behavior, and result truncation.


Contributing

See CONTRIBUTING.md.


License

MIT

About

Arrest is a small utility to easily structure and validate your REST api calls using pydantic and httpx

Topics

Resources

Code of conduct

Contributing

Stars

167 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages