# Dynamic CRM API Guide

## Why FastAPI

This API foundation uses **FastAPI + SQLAlchemy** because it gives:

- native OpenAPI/Swagger generation
- strong request/response validation with Pydantic
- high performance async-capable HTTP handling
- straightforward dependency injection for auth, DB access, and RBAC
- a clean path to background jobs, webhooks, and future GraphQL if needed

REST is the default choice here because the CRM needs stable integration contracts, predictable auth and caching boundaries, and simple external-system adoption. GraphQL can be layered in later for reporting or timeline composition if required.

## Architecture

The backend is structured as:

- `api/`: HTTP layer, versioned routers, request handling
- `services/`: business logic and orchestration
- `repositories/`: database access and query composition
- `models/`: SQLAlchemy persistence models
- `schemas/`: validated request/response contracts
- `core/`: config, security, rate limiting, error handling, response envelopes
- `db/`: engine, sessions, metadata, seed/bootstrap

This keeps transport logic, business rules, and persistence concerns separate.

## Versioning

All routes are namespaced under:

- `/api/v1/...`

This allows non-breaking iteration and future parallel versions like `/api/v2`.

## Authentication

Authentication uses JWT bearer tokens.

### Login

`POST /api/v1/auth/login`

```json
{
  "username_or_email": "admin",
  "password": "ChangeMe123!"
}
```

Response:

```json
{
  "success": true,
  "data": {
    "access_token": "jwt-token",
    "token_type": "bearer"
  },
  "error": null,
  "meta": {}
}
```

Use it as:

```http
Authorization: Bearer <access_token>
```

## Response Contract

Every endpoint returns the same envelope:

```json
{
  "success": true,
  "data": {},
  "error": null,
  "meta": {}
}
```

Error example:

```json
{
  "success": false,
  "data": null,
  "error": {
    "code": "contact_not_found",
    "message": "Contact not found."
  }
}
```

## Pagination, Filtering, Search, Sorting

List endpoints support:

- `limit`
- `cursor`
- `sort_by`
- `sort_order`
- resource-specific filters like `company_id`, `status`, `tag`, `kind`, `direction`
- text `search`

Example:

```bash
curl -X GET "http://127.0.0.1:8001/api/v1/contacts?search=alice&company_id=12&limit=25&sort_by=created_at&sort_order=desc" \
  -H "Authorization: Bearer <token>"
```

Cursor values are opaque and returned in `meta.next_cursor`.

## Endpoint Inventory

### Auth

- `POST /api/v1/auth/login`
- `GET /api/v1/auth/me`

### Contacts

- `GET /api/v1/contacts`
- `POST /api/v1/contacts`
- `POST /api/v1/contacts/bulk`
- `PATCH /api/v1/contacts/bulk`
- `GET /api/v1/contacts/{contact_id}`
- `PATCH /api/v1/contacts/{contact_id}`
- `GET /api/v1/contacts/{contact_id}/interactions`
- `POST /api/v1/contacts/{contact_id}/companies/{company_id}`
- `DELETE /api/v1/contacts/{contact_id}/companies/{company_id}`

### Companies

- `GET /api/v1/companies`
- `POST /api/v1/companies`
- `GET /api/v1/companies/{company_id}`
- `PATCH /api/v1/companies/{company_id}`
- `GET /api/v1/companies/{company_id}/contacts`
- `POST /api/v1/companies/{company_id}/contacts/{contact_id}`
- `DELETE /api/v1/companies/{company_id}/contacts/{contact_id}`

### Interactions

- `GET /api/v1/interactions`
- `POST /api/v1/interactions`

## Example Integrations

### Add a contact

```bash
curl -X POST "http://127.0.0.1:8001/api/v1/contacts" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Alice",
    "last_name": "Morgan",
    "email": "alice@example.com",
    "phone": "+44 20 7000 1234",
    "job_title": "Operations Director",
    "status": "new",
    "tags": ["enterprise", "uk"],
    "primary_company_id": 3
  }'
```

### Bulk update contacts

```bash
curl -X PATCH "http://127.0.0.1:8001/api/v1/contacts/bulk" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {"id": 10, "status": "qualified"},
      {"id": 11, "status": "qualified"}
    ]
  }'
```

### Create an interaction

```bash
curl -X POST "http://127.0.0.1:8001/api/v1/interactions" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": 10,
    "company_id": 3,
    "kind": "call",
    "direction": "outbound",
    "subject": "Discovery call",
    "body": "Prospect requested pricing follow-up.",
    "occurred_at": "2026-04-19T10:00:00Z"
  }'
```

## Security and Access Control

- JWT bearer authentication
- role-aware dependency hooks (`admin`, `user`)
- centralized API error handling
- request rate limiting middleware
- strict request validation via Pydantic

## Scaling Notes

For production scale, the next upgrades should be:

- PostgreSQL instead of SQLite
- Redis-backed rate limiting instead of in-memory storage
- background workers for emails, webhooks, and activity fan-out
- read models or search indexing for large contact sets
- DB indexes on:
  - `contacts.email`
  - `contacts.primary_company_id`
  - `contacts.status`
  - `companies.name`
  - `companies.domain`
  - `interactions.contact_id`
  - `interactions.company_id`
  - `interactions.occurred_at`

## Extensibility Notes

This structure is ready to extend with:

- deals and pipelines via new models/services/routers
- unified activity timelines over `interactions`
- webhooks and outbound integration jobs
- campaign modules, pipeline stages, SLA workflows

## OpenAPI

FastAPI exposes the generated spec at:

- `/api/openapi.json`

And interactive docs at:

- `/docs`
- `/redoc`

To export a checked-in spec file:

```powershell
python crm_api/scripts/export_openapi.py
```
