# API Client Quick Reference

> **TL;DR:** Use the auto-generated TypeScript client instead of manual API calls for type safety and schema validation.

## 🚀 Quick Start

### 1. Generate/Update Client

```bash
# Ensure API server is running first!
cd web
npm run generate:api
```

### 2. Import and Use

```typescript
import { PacksService, AuthService, ActionsService } from '@/api';
import type { CreatePackRequest, PackResponse } from '@/api';

// All API calls are now type-safe! ✅
const packs = await PacksService.listPacks({ page: 1, pageSize: 50 });
```

## 📚 Common Operations

### Authentication

```typescript
import { AuthService } from '@/api';

// Login
const response = await AuthService.login({
  requestBody: { login: 'admin', password: 'secret123' }
});
const { access_token, refresh_token, user } = response.data;

// Get current user
const currentUser = await AuthService.getCurrentUser();

// Refresh token
const refreshed = await AuthService.refreshToken({
  requestBody: { refresh_token }
});

// Register new user
await AuthService.register({
  requestBody: {
    login: 'newuser',
    password: 'strongpass',
    display_name: 'New User'
  }
});
```

### Packs

```typescript
import { PacksService } from '@/api';
import type { CreatePackRequest, UpdatePackRequest } from '@/api';

// List packs
const packs = await PacksService.listPacks({ page: 1, pageSize: 50 });

// Get single pack
const pack = await PacksService.getPack({ ref: 'core' });

// Create pack
const newPack = await PacksService.createPack({
  requestBody: {
    ref: 'my-pack',
    label: 'My Custom Pack',
    description: 'A pack for custom automations',
    version: '1.0.0'
  }
});

// Update pack
const updated = await PacksService.updatePack({
  ref: 'my-pack',
  requestBody: {
    label: 'Updated Pack Name',
    description: 'New description'
  }
});

// Delete pack
await PacksService.deletePack({ ref: 'my-pack' });
```

### Actions

```typescript
import { ActionsService } from '@/api';

// List actions
const actions = await ActionsService.listActions({ page: 1, pageSize: 50 });

// Get action
const action = await ActionsService.getAction({ ref: 'slack.post_message' });

// Create action
const newAction = await ActionsService.createAction({
  requestBody: {
    ref: 'slack.post_message',
    pack: 1,
    label: 'Post Message to Slack',
    description: 'Posts a message to a Slack channel',
    entrypoint: '/actions/slack/post_message.py',
    param_schema: { /* JSON Schema */ }
  }
});
```

### Rules

```typescript
import { RulesService } from '@/api';

// List rules
const rules = await RulesService.listRules({ page: 1, pageSize: 50 });

// Create rule
const rule = await RulesService.createRule({
  requestBody: {
    ref: 'webhook-to-slack',
    label: 'Webhook to Slack',
    pack: 1,
    trigger: 'webhook.received',
    action: 'slack.post_message',
    criteria: { /* Rule conditions */ },
    parameters: { /* Action parameters */ }
  }
});
```

### Executions

```typescript
import { ExecutionsService } from '@/api';

// List executions
const executions = await ExecutionsService.listExecutions({
  page: 1,
  perPage: 50,
  status: 'Running' // Optional filter
});

// Get execution details
const execution = await ExecutionsService.getExecution({ id: 123 });

// Cancel execution
await ExecutionsService.cancelExecution({ id: 123 });

// Re-run execution
const rerun = await ExecutionsService.rerunExecution({ id: 123 });
```

### Events

```typescript
import { EventsService } from '@/api';

// List events
const events = await EventsService.listEvents({
  page: 1,
  perPage: 50,
  triggerRef: 'webhook.received' // Optional filter
});

// Get event details
const event = await EventsService.getEvent({ id: 456 });
```

## 🔄 React Query Integration

### Query Hooks

```typescript
import { useQuery } from '@tanstack/react-query';
import { PacksService } from '@/api';

function PacksList() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['packs'],
    queryFn: () => PacksService.listPacks({ page: 1, pageSize: 50 })
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {data?.data.items.map(pack => (
        <li key={pack.id}>{pack.label}</li>
      ))}
    </ul>
  );
}
```

### Mutation Hooks

```typescript
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { PacksService } from '@/api';
import type { CreatePackRequest } from '@/api';

function CreatePackForm() {
  const queryClient = useQueryClient();

  const mutation = useMutation({
    mutationFn: (data: CreatePackRequest) =>
      PacksService.createPack({ requestBody: data }),
    onSuccess: () => {
      // Invalidate and refetch
      queryClient.invalidateQueries({ queryKey: ['packs'] });
    }
  });

  const handleSubmit = (formData: CreatePackRequest) => {
    mutation.mutate(formData);
  };

  return (
    <form onSubmit={e => {
      e.preventDefault();
      handleSubmit({
        ref: 'my-pack',
        label: 'My Pack',
        description: 'Description'
      });
    }}>
      {/* form fields */}
      <button type="submit" disabled={mutation.isPending}>
        {mutation.isPending ? 'Creating...' : 'Create Pack'}
      </button>
    </form>
  );
}
```

## 🎯 Error Handling

```typescript
import { ApiError } from '@/api';

try {
  await PacksService.getPack({ ref: 'nonexistent' });
} catch (error) {
  if (error instanceof ApiError) {
    console.error(`Status: ${error.status}`);
    console.error(`Message: ${error.message}`);
    console.error(`Body:`, error.body);

    switch (error.status) {
      case 401:
        // Unauthorized - redirect to login
        break;
      case 404:
        // Not found
        break;
      case 422:
        // Validation error
        console.error('Validation errors:', error.body);
        break;
      default:
        // Other errors
        break;
    }
  }
}
```

## 📦 Available Services

| Service | Description | Common Methods |
|---------|-------------|----------------|
| `AuthService` | Authentication | `login`, `register`, `getCurrentUser`, `refreshToken` |
| `PacksService` | Pack management | `listPacks`, `getPack`, `createPack`, `updatePack` |
| `ActionsService` | Action CRUD | `listActions`, `getAction`, `createAction`, `updateAction` |
| `RulesService` | Rule management | `listRules`, `getRule`, `createRule`, `updateRule` |
| `TriggersService` | Trigger config | `listTriggers`, `getTrigger`, `createTrigger` |
| `SensorsService` | Sensor monitoring | `listSensors`, `getSensor`, `createSensor` |
| `ExecutionsService` | Execution tracking | `listExecutions`, `getExecution`, `cancelExecution` |
| `EventsService` | Event history | `listEvents`, `getEvent` |
| `InquiriesService` | Human-in-the-loop | `listInquiries`, `getInquiry`, `respondToInquiry` |
| `WorkflowsService` | Workflow orchestration | `listWorkflows`, `getWorkflow`, `createWorkflow` |
| `HealthService` | Health checks | `health`, `healthDetailed`, `healthReady` |
| `SecretsService` | Secret management | `listKeys`, `getKey`, `createKey` |
| `EnforcementsService` | Rule enforcements | `listEnforcements`, `getEnforcement` |

## 🚨 Common Mistakes

### ❌ Don't Do This

```typescript
// Manual axios calls - NO TYPE SAFETY!
import { apiClient } from '@/lib/api-client';

const response = await apiClient.post('/api/v1/packs', {
  name: 'my-pack',      // ❌ Wrong field name
  system: false         // ❌ Wrong field name
});
```

### ✅ Do This Instead

```typescript
// Generated client - FULL TYPE SAFETY!
import { PacksService } from '@/api';
import type { CreatePackRequest } from '@/api';

const response = await PacksService.createPack({
  requestBody: {
    ref: 'my-pack',        // ✅ Correct field (enforced by TypeScript)
    label: 'My Pack',      // ✅ Correct field
    is_standard: false     // ✅ Correct field
  }
});
```

## 🔧 Troubleshooting

### Client out of sync with backend?

```bash
npm run generate:api
```

### Token not being sent?

Make sure `src/lib/api-config.ts` is imported in `src/main.tsx`:

```typescript
import './lib/api-config'; // ← This line must be present
```

### TypeScript errors after generation?

The backend schema changed. Update your code to match the new schema:

1. Read the error messages
2. Check what changed in the OpenAPI spec at http://localhost:8080/docs
3. Update your code accordingly

## 📖 Full Documentation

- **Detailed Guide:** `src/api/README.md`
- **Migration Guide:** `MIGRATION-TO-GENERATED-CLIENT.md`
- **Architecture:** `../docs/openapi-client-generation.md`
- **Interactive Docs:** http://localhost:8080/docs

## 💡 Pro Tips

1. **Always regenerate after backend changes** to stay in sync
2. **Use TypeScript** - let the compiler catch errors
3. **Create custom hooks** - wrap services in React Query hooks
4. **Don't edit generated files** - they'll be overwritten
5. **Use generated types** - import from `@/api`, not manual definitions
6. **Leverage auto-completion** - your IDE knows the full API schema

---

**Remember:** The generated client is your single source of truth for API interactions. Use it exclusively for type safety and automatic schema validation! 🎉