> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nihalxkumar.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Zingat API Reference

> Complete API documentation for Zingat endpoints - Create, read, update, and manage clips

# Zingat API Reference

Complete documentation for all Zingat API endpoints and web UI routes. API endpoints return JSON responses and support standard HTTP methods.

## Base URL

All API endpoints are relative to the base URL:

```
http://localhost:8000/api
```

## Authentication

API endpoints require an API key for authentication. Generate an API key using `GET /api/clip/key`. Password-protected clips require the password to be provided when accessing via web UI.

## Web UI Routes

### Home Page

**Endpoint**: `GET /`

Displays the home page with clip creation form.

### Create Clip (Web Form)

**Endpoint**: `POST /`

Creates a new clip from web form submission.

### View Clip

**Endpoint**: `GET /clip/<shortcode>`

View a clip by its shortcode. If password-protected, displays password prompt.

### Submit Password

**Endpoint**: `POST /clip/<shortcode>`

Submit password for password-protected clip.

### Raw Content

**Endpoint**: `GET /clip/raw/<shortcode>`

Get raw content only (no HTML wrapper).

## API Endpoints

### Generate API Key

Generate a new API key for programmatic access.

**Endpoint**: `GET /api/clip/key`

<ResponseExample>
  ```json Success theme={null}
  {
    "api_key": "generated-api-key-here"
  }
  ```
</ResponseExample>

### Create Clip

Create a new clip with optional password protection and expiry.

**Endpoint**: `POST /api/clip`

<ParamField body="content" type="string" required>
  The text content to store.
</ParamField>

<ParamField body="title" type="string">
  Optional title for the clip.
</ParamField>

<ParamField body="password" type="string">
  Optional password for access protection.
</ParamField>

<ParamField body="expires" type="string">
  Optional expiration date in YYYY-MM-DD format.
</ParamField>

<RequestExample>
  ```bash xh theme={null}
  # Per project rule, prefer xh over curl
  xh POST http://localhost:8000/api/clip \
    Content-Type:application/json \
    X-API-Key:your-api-key \
    content='Your clip content here' \
    title='Optional Title' \
    password='optional_password' \
    expires='2024-12-31'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "shortcode": "abc123",
    "url": "http://localhost:8000/clip/abc123",
    "expires": "2024-12-31T00:00:00Z"
  }
  ```
</ResponseExample>

### Get Clip

Retrieve a clip by its shortcode. Requires API key.

**Endpoint**: `GET /api/clip/<shortcode>`

**Headers**:

```
X-API-Key: your-api-key
```

**Response**:

```json theme={null}
{
  "clip_id": "uuid-here",
  "shortcode": "abc123",
  "content": "Your clip content here",
  "title": "Optional Title",
  "posted": "2025-11-05T10:00:00Z",
  "expires": "2024-12-31T00:00:00Z",
  "hits": 42,
  "password": null
}
```

### Update Clip

Update an existing clip. Requires API key.

**Endpoint**: `PUT /api/clip`

**Headers**:

```
X-API-Key: your-api-key
Content-Type: application/json
```

**Request Body**:

```json theme={null}
{
  "shortcode": "abc123",
  "content": "Updated content",
  "title": "Updated Title",
  "password": "new_password",
  "expires": "2024-12-31"
}
```

**Response**:

```json theme={null}
{
  "shortcode": "abc123",
  "url": "http://localhost:8000/clip/abc123"
}
```

## Error Responses

All endpoints return standard HTTP status codes with JSON error messages:

### 400 Bad Request

```json theme={null}
{
  "error": "Invalid request parameters",
  "details": "Content cannot be empty"
}
```

### 401 Unauthorized

```json theme={null}
{
  "error": "API key required",
  "message": "This endpoint requires API key authentication"
}
```

### 403 Forbidden

```json theme={null}
{
  "error": "Invalid password",
  "message": "The provided password is incorrect"
}
```

### 404 Not Found

```json theme={null}
{
  "error": "Clip not found",
  "message": "The requested clip does not exist or has expired"
}
```

### 429 Too Many Requests

```json theme={null}
{
  "error": "Rate limit exceeded",
  "message": "Too many requests, please try again later"
}
```

## Rate Limiting

API endpoints may be rate limited to prevent abuse. Web UI routes use cookie-based password persistence for protected clips.

## Content Limits

* **Minimum content length**: 1 character
* **Expiry dates**: Custom date format (YYYY-MM-DD)

## Example Usage

<CodeGroup>
  ```bash xh theme={null}
  # Generate API key first
  API_KEY=$(xh GET http://localhost:8000/api/clip/key | jq -r '.api_key')

  # Create a clip (preferred tooling)
  xh POST http://localhost:8000/api/clip \
    Content-Type:application/json \
    X-API-Key:$API_KEY \
    content='Hello, this is a test clip!' \
    title='Test Clip' \
    password='secret123' \
    expires='2024-12-31'
  ```

  ```javascript Node.js theme={null}
  // Generate API key
  const keyResponse = await fetch('http://localhost:8000/api/clip/key');
  const { api_key } = await keyResponse.json();

  // Create clip
  await fetch('http://localhost:8000/api/clip', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': api_key
    },
    body: JSON.stringify({
      content: 'Hello, this is a test clip!',
      title: 'Test Clip',
      password: 'secret123',
      expires: '2024-12-31'
    })
  });
  ```

  ```python Python theme={null}
  import requests

  # Generate API key
  key_response = requests.get('http://localhost:8000/api/clip/key')
  api_key = key_response.json()['api_key']

  # Create clip
  requests.post('http://localhost:8000/api/clip', json={
    'content': 'Hello, this is a test clip!',
    'title': 'Test Clip',
    'password': 'secret123',
    'expires': '2024-12-31'
  }, headers={'X-API-Key': api_key})
  ```
</CodeGroup>

## Response Codes Summary

| Code | Description                            |
| ---- | -------------------------------------- |
| 200  | Success                                |
| 201  | Created successfully                   |
| 400  | Bad request parameters / API key error |
| 401  | API key required or invalid            |
| 403  | Invalid password                       |
| 404  | Clip not found or expired              |
| 429  | Rate limit exceeded                    |
| 500  | Internal server error                  |
