# POST /v1/bloggers/track

Asynchronously start tracking a creator (channel) across supported platforms. The endpoint enqueues a job that resolves the channel, creates the blogger record, and enqueues the initial video backfill. Poll [`GET /v1/bloggers/jobs/{job_id}`](./jobs) to track progress.

## 📋 Overview

| Property | Value |
|----------|-------|
| **Method** | `POST` |
| **Endpoint** | `https://api.influtics.com/v1/bloggers/track` |
| **Auth Required** | ✅ Yes |
| **Credits Cost** | 0 credits (free — heavy lifting is asynchronous) |

## 🔐 Headers

```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

## 📝 Request

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `platform` | `string` | ✅ **Required** | One of: `instagram`, `tiktok`, `youtube`, `vk` |
| `username` | `string` | ✅ **Required** | Channel username (no leading `@`, max 64 chars) |
| `initial_videos_count` | `integer` | ✅ **Required** | Number of initial videos to backfill, range `1 ≤ N ≤ 500` |

### Example Request

```bash
curl -X POST https://api.influtics.com/v1/bloggers/track \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "instagram",
    "username": "bar.films",
    "initial_videos_count": 10
  }'
```

## ✅ Response

### Success Response (202 Accepted)

**Headers:**
- `Location: /v1/bloggers/jobs/{job_id}`
- `Retry-After: 1`

**Body:**

```json
{
  "success": true,
  "data": {
    "job_id": "8f3a7e21-6c4f-4d3b-9c2a-1e0b8d7c6f5a",
    "status": "queued",
    "status_url": "/v1/bloggers/jobs/8f3a7e21-6c4f-4d3b-9c2a-1e0b8d7c6f5a",
    "platform": "instagram",
    "username": "bar.films",
    "estimated_duration_seconds": 30,
    "polling": {
      "retry_after_seconds": 1
    }
  },
  "meta": {
    "request_id": "6e10c2ba-dda6-4a3d-92f1-8a224c5a088c"
  }
}
```

### Response Fields

| Field | Type | Description |
|-------|------|-------------|
| `data.job_id` | `string` | Internal job UUID. Poll this against [`GET /v1/bloggers/jobs/{job_id}`](./jobs). |
| `data.status` | `string` | Initial state — always `"queued"` on a successful 202. |
| `data.status_url` | `string` | Relative URL to poll for status updates. |
| `data.platform` | `string` | Echoed platform from the request. |
| `data.username` | `string` | Echoed username from the request. |
| `data.estimated_duration_seconds` | `number` | Indicative upper bound for completion (typical: 5–60 s). |
| `data.polling.retry_after_seconds` | `number` | Server-recommended initial poll delay (matches `Retry-After` header). |
| `meta.request_id` | `string` | Unique request identifier (also echoed in error responses). |

## ⚠️ Error Responses

All errors share the standard envelope `{ success: false, error: { code, message, request_id, ... } }`. The table below lists every documented `code` and the conditions that trigger it.

| Status | `code` | Trigger | Additional `error` fields |
|--------|--------|---------|---------------------------|
| `400` | `VALIDATION_ERROR` | Missing, empty, or out-of-range field; unknown platform value | `field`; for unknown platform, also `allowed_platforms: ["instagram", "tiktok", "youtube", "vk"]` |
| `402` | `PAID_PLAN_REQUIRED` | Free-tier API key attempted to track | `upgrade_url` |
| `409` | `CREATOR_ALREADY_TRACKED` | An active `tracked_accounts` row already exists for this `(platform, username)` in your org | `tracked_account_id` |
| `409` | `CREATOR_REACTIVATE_IN_FLIGHT` | A previously deactivated creator is being reactivated by another job | — |
| `409` | `CREATOR_TRACK_IN_FLIGHT` | Another queued or processing job exists for the same `(org, platform, username)` | `job_id`, `status_url` |
| `422` | `SUBSCRIPTION_LIMIT` | Tracking would exceed the `tracked_videos` quota after the initial backfill | `field: "tracked_videos"`, `limit`, `current`, `estimated_after`, `upgrade_url` |
| `422` | `TRACKED_CREATORS_LIMIT` | Tracking would exceed the `tracked_creators` cap | `field: "tracked_creators"`, `limit`, `current`, `upgrade_url` |
| `503` | `RETRYABLE_ERROR` | A downstream lookup failed; the job was not enqueued | — |

## 🔧 Features

### Asynchronous by Design
- Returns `202 Accepted` immediately and persists a job row in `track_account_jobs`.

### Built-in Dedup
- Active creator (`is_active=true`) → `409 CREATOR_ALREADY_TRACKED`.
- Deactivated creator with a reactivation in flight → `409 CREATOR_REACTIVATE_IN_FLIGHT`.
- Concurrent track-job for the same `(org, platform, username)` → `409 CREATOR_TRACK_IN_FLIGHT` with the existing `job_id` returned.

### Tier Enforcement
- `enforcePaidPlan` rejects free-tier API keys with `402 PAID_PLAN_REQUIRED`.
- `tracked_videos` and `tracked_creators` caps are checked up-front so a partial state is never written.

## 🎯 Use Cases

- **CRM Imports**: Bulk-discover and onboard creators from a CSV import (track per-creator from your importer).
- **Competitor Watchlists**: Programmatic onboarding of competitor channel lists.
- **Backend-to-Backend Workflows**: Chain into influencer discovery pipelines without human-in-the-loop dashboard clicks.
- **CI/CD Integration**: Trigger tracking from a build/test run before downstream jobs that depend on stats.

## 📈 What Happens Next?

1. **Initial poll** — Wait the `Retry-After` seconds (default `1`) before the first poll of `GET /v1/bloggers/jobs/{job_id}`.
2. **Backoff** — Use exponential backoff with jitter: `1s → 2s → 4s → 8s → max 30s`.
3. **Stop conditions** — Stop polling when `status` is `succeeded` or `error`, or when the response is `410`.
4. **Stuck jobs** — Jobs stuck in `processing` for over `JOB_TIMEOUT` (default `1h`) are auto-reset to `error / JOB_TIMEOUT` by the hourly stuck-jobs sweeper cron.
5. **Post-success** — On `succeeded`, the `result` block contains the `tracked_account_id` and `blogger_id`. Continue to use `GET /v1/videos/stats?blogger_username=...` to fetch stats once backfill completes.

## 📊 Rate Limits

- **Requests**: 60 requests per minute per API key (same envelope as other paid endpoints).
- **Subscription limits (per tier)**:
  - `tracked_videos_limit` — videos quota enforced up-front; tracking fails with `422 SUBSCRIPTION_LIMIT`.
  - `tracked_creators_limit` — creator cap enforced up-front; tracking fails with `422 TRACKED_CREATORS_LIMIT`.
  - Default creator caps: free = 10, pro = 200, business = 300.

---

**Related**: [Get Job Status →](./jobs) | [Blogger Info →](./info)
