# DigiFlow API Documentation

**Version:** 1.0.0  
**Base URL:** `https://api.digiflow.app/v1`

DigiFlow is a multi-tenant SaaS platform for field service work order management. This API enables companies to manage their operations: create work orders, assign technicians, optimize routes, and provide real-time visibility to all stakeholders.

## Table of Contents

- [Authentication](#authentication)
- [Multi-Tenancy](#multi-tenancy)
- [Services Overview](#services-overview)
- [Authentication Service](#authentication-service)
- [Tenant Service](#tenant-service)
- [User Service](#user-service)
- [Work Order Service](#work-order-service)
- [Work Order Types Service](#work-order-types-service)
- [Work Order States Service](#work-order-states-service)
- [Work Order Search Service](#work-order-search-service)
- [Custom Fields Service](#custom-fields-service)
- [Technician Service](#technician-service)
- [Client Service](#client-service)
- [Asset Service](#asset-service)
- [Route Service](#route-service)
- [Delay Service](#delay-service)
- [Dashboard Service](#dashboard-service)
- [Evidence Service](#evidence-service)
- [Notification Service](#notification-service)
- [Realtime Service](#realtime-service)
- [Error Handling](#error-handling)
- [Rate Limits](#rate-limits)

---

## Authentication

DigiFlow uses OAuth 2.0 with JWT tokens for authentication.

### Token Format

All authenticated requests must include a Bearer token:

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

### Token Lifecycle

| Token Type | Lifetime | Usage |
|------------|----------|-------|
| Access Token | 15 minutes | API requests |
| Refresh Token | 7 days | Obtain new access tokens |

### Obtaining Tokens

**Password Grant** (first-party apps):

```http
POST /v1/auth/token
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "secret"
}
```

**Response:**

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "dGhpcyBpcyBhIHJlZnJl..."
}
```

### Refreshing Tokens

```http
POST /v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "dGhpcyBpcyBhIHJlZnJl..."
}
```

---

## Multi-Tenancy

DigiFlow is a multi-tenant platform. Each organization (tenant) has isolated data.

### How It Works

- Every user belongs to exactly one tenant
- All data is automatically scoped to the user's tenant
- Tenant ID is extracted from the JWT token (no manual header required)
- Database uses Row-Level Security (RLS) for isolation

### Tenant Registration

Organizations can self-register:

```http
POST /v1/tenants
Content-Type: application/json

{
  "name": "ACME Field Services",
  "subdomain": "acme",
  "admin_email": "admin@acme.com",
  "admin_password": "secure-password",
  "admin_first_name": "John",
  "admin_last_name": "Doe"
}
```

---

## Services Overview

DigiFlow API is organized into 17 services:

| Service | Description | Endpoints |
|---------|-------------|-----------|
| AuthService | Authentication & tokens | 4 |
| TenantService | Tenant management | 3 |
| UserService | User CRUD & roles | 6 |
| WorkOrderService | Work order lifecycle | 18 |
| WorkOrderTypeService | Work order type config | 5 |
| WorkOrderStateService | Workflow state machine | 9 |
| WorkOrderSearchService | Advanced search & stats | 7 |
| CustomFieldService | Dynamic custom fields | 7 |
| TechnicianService | Technician profiles | 7 |
| ClientService | Client profiles | 6 |
| AssetService | Asset management | 8 |
| RouteService | Route optimization | 3 |
| DelayService | SLA & delay tracking | 5 |
| DashboardService | Admin dashboards | 4 |
| EvidenceService | Photos, audio, notes | 5 |
| NotificationService | Preferences & tokens | 9 |
| RealtimeService | WebSocket subscriptions | 4 |

---

## Authentication Service

Handles user authentication and session management.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/auth/token` | Password grant login | No |
| POST | `/v1/auth/refresh` | Refresh access token | No |
| POST | `/v1/auth/logout` | Revoke all tokens | Yes |
| GET | `/v1/auth/me` | Get current user info | Yes |

### Get Current User

```http
GET /v1/auth/me
Authorization: Bearer <token>
```

**Response:**

```json
{
  "user_id": "usr_abc123",
  "tenant_id": "tnt_xyz789",
  "email": "tech@acme.com",
  "first_name": "Jane",
  "last_name": "Smith",
  "roles": ["technician"]
}
```

---

## Tenant Service

Manage tenant (organization) settings.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/tenants` | Register new tenant | No |
| GET | `/v1/tenants/current` | Get current tenant | Yes |
| PATCH | `/v1/tenants/current` | Update tenant settings | Admin |

---

## User Service

Manage users within a tenant.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/users` | Create user | Admin |
| GET | `/v1/users/{id}` | Get user by ID | Yes |
| GET | `/v1/users` | List users | Yes |
| PATCH | `/v1/users/{id}` | Update user | Admin |
| DELETE | `/v1/users/{id}` | Deactivate user | Admin |
| PATCH | `/v1/users/{id}/password` | Change password | Admin/Self |

### Roles

| Role | Description |
|------|-------------|
| `admin` | Full access to tenant data and settings |
| `technician` | Field worker, can view/update assigned work orders |
| `client` | Customer, can view their own work orders |

### Create User

```http
POST /v1/users
Authorization: Bearer <admin_token>
Content-Type: application/json

{
  "email": "newtech@acme.com",
  "password": "initial-password",
  "first_name": "Bob",
  "last_name": "Builder",
  "roles": ["technician"]
}
```

---

## Work Order Service

Core service for work order lifecycle management.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/work-orders` | Create work order | Admin |
| GET | `/v1/work-orders/{id}` | Get work order | Yes |
| PATCH | `/v1/work-orders/{id}` | Update work order | Admin |
| POST | `/v1/work-orders/{id}/archive` | Archive work order | Admin |
| POST | `/v1/work-orders/{id}/transition` | Change state | Yes |
| GET | `/v1/work-orders/{id}/history` | Get state history | Yes |
| POST | `/v1/work-orders/{id}/assignments` | Assign technician | Admin |
| DELETE | `/v1/work-orders/{id}/assignments/{tech_id}` | Remove assignment | Admin |
| GET | `/v1/work-orders/{id}/assignments` | List assignments | Yes |
| GET | `/v1/work-orders` | List work orders | Yes |
| GET | `/v1/work-orders/{id}/audit` | Get audit log | Admin |
| GET | `/v1/work-orders/my` | Technician's work orders | Tech |
| POST | `/v1/work-orders/{id}/problems` | Report problem | Tech |
| GET | `/v1/work-orders/{id}/problems` | List problems | Yes |
| POST | `/v1/work-orders/problems/{id}/acknowledge` | Acknowledge problem | Admin |
| POST | `/v1/work-orders/problems/{id}/resolve` | Resolve problem | Admin |
| POST | `/v1/work-orders/{id}/close` | Close work order | Tech |
| GET | `/v1/work-orders/client` | Client's work orders | Client |
| POST | `/v1/work-orders/{id}/satisfaction` | Submit rating | Client |
| GET | `/v1/work-orders/client/statistics` | Client stats | Client |

### Create Work Order

```http
POST /v1/work-orders
Authorization: Bearer <admin_token>
Content-Type: application/json

{
  "type_id": "wot_maintenance",
  "title": "AC Unit Repair",
  "description": "Customer reports AC not cooling",
  "priority": "PRIORITY_HIGH",
  "client_id": "usr_client123",
  "location": {
    "address": "123 Main St, City, ST 12345",
    "latitude": 40.7128,
    "longitude": -74.0060
  },
  "schedule": {
    "date": "2026-04-15",
    "time_start": "09:00",
    "time_end": "11:00"
  },
  "custom_fields": [
    {
      "field_id": "cf_equipment_type",
      "value": "HVAC"
    }
  ]
}
```

### Transition State

```http
POST /v1/work-orders/{id}/transition
Authorization: Bearer <token>
Content-Type: application/json

{
  "to_state_id": "wos_in_progress",
  "notes": "Arrived at location, starting work"
}
```

### Priority Levels

| Value | Description |
|-------|-------------|
| `PRIORITY_LOW` | Can be scheduled flexibly |
| `PRIORITY_MEDIUM` | Normal priority |
| `PRIORITY_HIGH` | Should be addressed soon |
| `PRIORITY_URGENT` | Immediate attention required |

---

## Work Order Types Service

Configure different types of work orders per tenant.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/work-order-types` | Create type | Admin |
| GET | `/v1/work-order-types/{id}` | Get type | Yes |
| GET | `/v1/work-order-types` | List types | Yes |
| PATCH | `/v1/work-order-types/{id}` | Update type | Admin |
| DELETE | `/v1/work-order-types/{id}` | Delete type | Admin |

### Example Types

- Installation
- Maintenance
- Repair
- Inspection
- Emergency

---

## Work Order States Service

Configure workflow states and transitions.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/work-order-states` | Create state | Admin |
| GET | `/v1/work-order-states/{id}` | Get state | Yes |
| GET | `/v1/work-order-states` | List states | Yes |
| PATCH | `/v1/work-order-states/{id}` | Update state | Admin |
| DELETE | `/v1/work-order-states/{id}` | Delete state | Admin |
| POST | `/v1/work-order-states/transitions` | Create transition | Admin |
| GET | `/v1/work-order-states/transitions` | List transitions | Yes |
| DELETE | `/v1/work-order-states/transitions/{id}` | Delete transition | Admin |
| GET | `/v1/work-order-states/{id}/available` | Get valid next states | Yes |

### State Properties

| Property | Description |
|----------|-------------|
| `is_initial` | Can be used when creating work orders |
| `is_terminal` | Work order is considered complete |
| `color` | Hex color for UI display |

### Example Workflow

```
[Pending] → [Assigned] → [In Progress] → [Completed]
                ↓               ↓
           [On Hold] ←─────────┘
                ↓
          [Cancelled]
```

---

## Work Order Search Service

Advanced search, filtering, and statistics.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| GET | `/v1/work-orders/search` | Full-text search | Yes |
| POST | `/v1/work-orders/filter` | Filter with criteria | Yes |
| GET | `/v1/work-orders/overdue` | List overdue work orders | Yes |
| GET | `/v1/work-orders/stats` | Overview stats | Admin |
| GET | `/v1/work-orders/stats/by-state` | Stats by state | Admin |
| GET | `/v1/work-orders/stats/by-priority` | Stats by priority | Admin |
| GET | `/v1/work-orders/stats/by-type` | Stats by type | Admin |
| GET | `/v1/work-orders/stats/by-date` | Stats by date range | Admin |

### List Overdue Work Orders

Returns work orders that are past their scheduled date and not completed.

```http
GET /v1/work-orders/overdue?page_size=20&page=1
Authorization: Bearer <token>
```

**Response:**

```json
{
  "work_orders": [
    {
      "id": "wo_123",
      "title": "AC Repair",
      "state_name": "Assigned",
      "state_color": "#FFA500",
      "priority": "PRIORITY_HIGH",
      "schedule": {
        "date": "2026-04-10"
      }
    }
  ],
  "total_count": 5
}
```

### Search Example

```http
POST /v1/work-orders/search
Authorization: Bearer <token>
Content-Type: application/json

{
  "query": "AC repair",
  "filters": {
    "state_ids": ["wos_pending", "wos_assigned"],
    "priority": "PRIORITY_HIGH",
    "date_from": "2026-04-01",
    "date_to": "2026-04-30",
    "technician_id": "usr_tech123"
  },
  "page_size": 20,
  "cursor": null
}
```

---

## Custom Fields Service

Define dynamic fields per work order type.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/custom-fields` | Create field definition | Admin |
| GET | `/v1/custom-fields/{id}` | Get field | Yes |
| GET | `/v1/custom-fields` | List fields | Yes |
| PATCH | `/v1/custom-fields/{id}` | Update field | Admin |
| DELETE | `/v1/custom-fields/{id}` | Delete field | Admin |
| GET | `/v1/work-order-types/{id}/custom-fields` | Fields for type | Yes |
| PUT | `/v1/work-orders/{id}/custom-fields` | Set field values | Yes |

### Field Types

| Type | Description | Example |
|------|-------------|---------|
| `TEXT` | Free text | "Equipment Model" |
| `NUMBER` | Numeric value | "Parts Used" |
| `DATE` | Date picker | "Warranty Expiry" |
| `SELECT` | Dropdown options | "Equipment Type" |
| `CHECKBOX` | Boolean | "Customer Present" |

---

## Technician Service

Manage technician profiles, availability, and certifications.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| GET | `/v1/technicians/{id}` | Get profile | Yes |
| GET | `/v1/technicians` | List technicians | Admin |
| PATCH | `/v1/technicians/{id}` | Update profile | Admin/Self |
| GET | `/v1/technicians/{id}/availability` | Get availability | Yes |
| PUT | `/v1/technicians/{id}/availability` | Set availability | Admin/Self |
| POST | `/v1/technicians/{id}/certifications` | Add certification | Admin |
| DELETE | `/v1/technicians/{id}/certifications/{cert_id}` | Remove cert | Admin |

### Availability Format

```json
{
  "schedule": {
    "monday": {"start": "08:00", "end": "17:00"},
    "tuesday": {"start": "08:00", "end": "17:00"},
    "wednesday": {"start": "08:00", "end": "17:00"},
    "thursday": {"start": "08:00", "end": "17:00"},
    "friday": {"start": "08:00", "end": "17:00"}
  },
  "exceptions": [
    {"date": "2026-04-20", "available": false, "reason": "PTO"}
  ]
}
```

---

## Client Service

Manage client profiles and service history.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| GET | `/v1/clients/{id}` | Get profile | Yes |
| GET | `/v1/clients` | List clients | Admin |
| PATCH | `/v1/clients/{id}` | Update profile | Admin |
| GET | `/v1/clients/{id}/work-orders` | Client's work orders | Yes |
| GET | `/v1/clients/{id}/statistics` | Client statistics | Yes |
| GET | `/v1/clients/{id}/service-history` | Service history | Yes |

---

## Asset Service

Track equipment and assets at client locations.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/assets` | Create asset | Admin |
| GET | `/v1/assets/{id}` | Get asset | Yes |
| GET | `/v1/assets` | List assets | Yes |
| PATCH | `/v1/assets/{id}` | Update asset | Admin |
| DELETE | `/v1/assets/{id}` | Delete asset | Admin |
| GET | `/v1/clients/{id}/assets` | Client's assets | Yes |
| GET | `/v1/assets/{id}/service-history` | Asset history | Yes |
| POST | `/v1/work-orders/{id}/assets` | Link asset to WO | Yes |

### Asset Example

```json
{
  "id": "ast_hvac123",
  "client_id": "usr_client456",
  "name": "Main Office HVAC Unit",
  "type": "HVAC",
  "serial_number": "HVAC-2024-001",
  "location": {
    "address": "123 Main St, Suite 100",
    "latitude": 40.7128,
    "longitude": -74.0060
  },
  "install_date": "2024-01-15",
  "warranty_expiry": "2027-01-15"
}
```

---

## Route Service

Optimize technician routes for the day.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/routes/optimize` | Optimize route | Yes |
| GET | `/v1/routes/travel-time` | Estimate travel time | Yes |
| GET | `/v1/routes/nearest-technicians` | Find nearest techs | Yes |
| GET | `/v1/routes/{technician_id}` | Get saved custom route | Yes |
| PUT | `/v1/routes/{technician_id}` | Save custom route | Yes |

### Optimize Route

```http
POST /v1/routes/optimize
Authorization: Bearer <token>
Content-Type: application/json

{
  "technician_id": "usr_tech123",
  "date": "2026-04-15",
  "start_location": {
    "lat": 40.7128,
    "lng": -74.0060
  }
}
```

**Response:**

```json
{
  "stops": [
    {"work_order_id": "wo_abc", "sequence": 1, "estimated_arrival": "09:15", "travel_time_minutes": 15},
    {"work_order_id": "wo_def", "sequence": 2, "estimated_arrival": "11:30", "travel_time_minutes": 25},
    {"work_order_id": "wo_ghi", "sequence": 3, "estimated_arrival": "14:00", "travel_time_minutes": 30}
  ],
  "total_travel_time_minutes": 70,
  "total_distance_km": 45.5,
  "optimization_status": "optimized"
}
```

### Save Custom Route

Override the optimized route with a manual order:

```http
PUT /v1/routes/usr_tech123
Authorization: Bearer <token>
Content-Type: application/json

{
  "technician_id": "usr_tech123",
  "date": "2026-04-15",
  "stops": [
    {"work_order_id": "wo_ghi", "sequence": 1},
    {"work_order_id": "wo_abc", "sequence": 2},
    {"work_order_id": "wo_def", "sequence": 3}
  ]
}
```

### Get Saved Route

```http
GET /v1/routes/usr_tech123?date=2026-04-15
Authorization: Bearer <token>
```

**Response:**

```json
{
  "has_custom_route": true,
  "stops": [
    {"work_order_id": "wo_ghi", "sequence": 1, "work_order_title": "Install Solar"},
    {"work_order_id": "wo_abc", "sequence": 2, "work_order_title": "AC Repair"},
    {"work_order_id": "wo_def", "sequence": 3, "work_order_title": "Maintenance"}
  ],
  "saved_at": "2026-04-14T18:30:00Z"
}
```

---

## Delay Service

Track work order delays and SLA compliance.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| GET | `/v1/delays` | List active delays | Admin |
| GET | `/v1/delays/{id}` | Get delay details | Admin |
| POST | `/v1/delays/{id}/acknowledge` | Acknowledge delay | Admin |
| POST | `/v1/delays/{id}/resolve` | Resolve delay | Admin |
| GET | `/v1/delay-configurations` | Get SLA configs | Admin |

### Delay Types

| Type | Description |
|------|-------------|
| `not_started` | Work order not started by scheduled time |
| `running_late` | Work order taking longer than expected |
| `sla_breach` | SLA threshold exceeded |

---

## Dashboard Service

Admin dashboard widgets and metrics.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| GET | `/v1/dashboard` | Get dashboard layout | Admin |
| GET | `/v1/dashboard/widgets/{id}` | Get widget data | Admin |
| PUT | `/v1/dashboard` | Update layout | Admin |
| GET | `/v1/dashboard/metrics` | Real-time metrics | Admin |

---

## Evidence Service

Upload and manage work order evidence (photos, audio, notes).

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| POST | `/v1/evidence` | Upload evidence | Yes |
| GET | `/v1/evidence/{id}` | Get evidence | Yes |
| GET | `/v1/work-orders/{id}/evidence` | List evidence | Yes |
| DELETE | `/v1/evidence/{id}` | Delete evidence | Admin/Owner |
| POST | `/v1/work-orders/{id}/comments` | Add text comment | Yes |

### Evidence Types

| Type | Max Size | Description |
|------|----------|-------------|
| `PHOTO` | 10 MB | JPEG, PNG, HEIC images |
| `AUDIO` | 20 MB | MP3, M4A, WAV recordings |
| `TEXT` | - | Text comments/notes |

### Upload Photo

```http
POST /v1/evidence
Authorization: Bearer <token>
Content-Type: application/json

{
  "work_order_id": "wo_abc123",
  "type": "EVIDENCE_TYPE_PHOTO",
  "filename": "before_repair.jpg",
  "content": "<base64-encoded-image>",
  "metadata": {
    "latitude": 40.7128,
    "longitude": -74.0060,
    "captured_at": "2026-04-15T10:30:00Z"
  }
}
```

**Response:**

```json
{
  "id": "evi_xyz789",
  "work_order_id": "wo_abc123",
  "type": "EVIDENCE_TYPE_PHOTO",
  "original_filename": "before_repair.jpg",
  "file_size": 1048576,
  "mime_type": "image/jpeg",
  "download_url": "https://storage.digiflow.app/...",
  "thumbnail_url": "https://storage.digiflow.app/thumb/...",
  "metadata": {
    "latitude": 40.7128,
    "longitude": -74.0060,
    "captured_at": "2026-04-15T10:30:00Z"
  },
  "uploaded_by_name": "Jane Tech",
  "uploaded_at": "2026-04-15T10:31:15Z"
}
```

---

## Notification Service

Manage notification preferences and device tokens.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| GET | `/v1/notifications/preferences` | Get preferences | Yes |
| PUT | `/v1/notifications/preferences` | Update preferences | Yes |
| POST | `/v1/notifications/devices` | Register device | Yes |
| DELETE | `/v1/notifications/devices/{token}` | Unregister device | Yes |
| GET | `/v1/notifications` | List notifications | Yes |
| POST | `/v1/notifications/{id}/read` | Mark as read | Yes |
| POST | `/v1/notifications/read-all` | Mark all read | Yes |
| GET | `/v1/notifications/unread-count` | Get unread count | Yes |
| POST | `/v1/notifications/test` | Send test notification | Yes |

### Notification Channels

| Channel | Description |
|---------|-------------|
| `email` | SendGrid email notifications |
| `push` | FCM (Android/Web) and APNs (iOS) |
| `in_app` | In-app notification center |

### Notification Types

- `work_order_assigned` - New assignment
- `work_order_state_changed` - Status update
- `work_order_delayed` - Delay detected
- `new_evidence` - Evidence uploaded
- `problem_reported` - Problem on work order
- `satisfaction_received` - Client rating received

### Update Preferences

```http
PUT /v1/notifications/preferences
Authorization: Bearer <token>
Content-Type: application/json

{
  "email_enabled": true,
  "push_enabled": true,
  "work_order_assigned": {"email": true, "push": true},
  "work_order_state_changed": {"email": false, "push": true},
  "work_order_delayed": {"email": true, "push": true}
}
```

### Register Device

```http
POST /v1/notifications/devices
Authorization: Bearer <token>
Content-Type: application/json

{
  "token": "fcm-or-apns-token",
  "platform": "PLATFORM_IOS",
  "device_name": "iPhone 15 Pro"
}
```

---

## Realtime Service

WebSocket connections for real-time updates.

### Endpoints

| Method | Endpoint | Description | Auth |
|--------|----------|-------------|------|
| WS | `/v1/realtime/ws` | WebSocket connection | Yes |
| GET | `/v1/realtime/online` | Get online users | Admin |
| POST | `/v1/realtime/subscribe` | gRPC stream subscribe | Yes |
| POST | `/v1/realtime/broadcast` | Admin broadcast | Admin |

### WebSocket Connection

```javascript
const ws = new WebSocket('wss://api.digiflow.app/v1/realtime/ws');

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'auth',
    token: 'Bearer <access_token>'
  }));
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log('Received:', message);
};
```

### Event Types

| Event | Description | Payload |
|-------|-------------|---------|
| `work_order.created` | New work order | WorkOrder object |
| `work_order.updated` | Work order changed | WorkOrder object |
| `work_order.state_changed` | State transition | StateChange object |
| `work_order.assigned` | Tech assigned | Assignment object |
| `evidence.uploaded` | New evidence | Evidence object |
| `notification` | User notification | Notification object |
| `delay.detected` | Delay alert | Delay object |

---

## Error Handling

### Error Response Format

```json
{
  "code": 3,
  "message": "Invalid argument: email is required",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.BadRequest",
      "field_violations": [
        {"field": "email", "description": "Email is required"}
      ]
    }
  ]
}
```

### gRPC Status Codes

| Code | Name | HTTP | Description |
|------|------|------|-------------|
| 0 | OK | 200 | Success |
| 1 | CANCELLED | 499 | Request cancelled |
| 2 | UNKNOWN | 500 | Unknown error |
| 3 | INVALID_ARGUMENT | 400 | Bad request |
| 5 | NOT_FOUND | 404 | Resource not found |
| 7 | PERMISSION_DENIED | 403 | Insufficient permissions |
| 9 | FAILED_PRECONDITION | 400 | Operation precondition failed |
| 10 | ABORTED | 409 | Conflict |
| 11 | OUT_OF_RANGE | 400 | Value out of range |
| 12 | UNIMPLEMENTED | 501 | Not implemented |
| 13 | INTERNAL | 500 | Internal server error |
| 14 | UNAVAILABLE | 503 | Service unavailable |
| 16 | UNAUTHENTICATED | 401 | Authentication required |

---

## Rate Limits

| Endpoint Category | Rate Limit |
|-------------------|------------|
| Authentication | 10 req/min |
| Read operations | 100 req/min |
| Write operations | 30 req/min |
| File uploads | 10 req/min |
| Search | 30 req/min |

Rate limit headers:

```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1618502400
```

---

## OpenAPI Specification

Interactive API documentation is available via Swagger UI:

- **Swagger UI:** `https://api.digiflow.app/docs`
- **OpenAPI JSON:** `https://api.digiflow.app/docs/openapi/digiflow-api.swagger.json`

---

## gRPC API

For service-to-service communication, DigiFlow exposes a native gRPC API:

- **Host:** `grpc.digiflow.app:443`
- **Proto files:** Available in the `proto/` directory

### Example (Go)

```go
conn, err := grpc.Dial("grpc.digiflow.app:443", grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
if err != nil {
    log.Fatal(err)
}
defer conn.Close()

client := workorderv1.NewWorkOrderServiceClient(conn)
resp, err := client.GetWorkOrder(ctx, &workorderv1.GetWorkOrderRequest{Id: "wo_abc123"})
```

---

## SDKs

Official SDKs (coming soon):

- Go
- TypeScript/JavaScript
- Swift (iOS)
- Kotlin (Android)

---

*Last updated: April 2026*
