# Create a summary — Shorty API

> Starts an async summary job for a YouTube video, a web page, or pasted text, selected by the `source` field. Usually responds 202 with a `Location` header and a `job_id` you can poll at GET /v1/jobs/{id} (send an `Idempotency-Key` header to make retries safe). If the exact source was already summarized in the requested language it responds 200 `already_complete` with the `article_id` and no job to poll. A web-page `url` whose path ends in `.doc` (a legacy Word file, which the web-page summarizer cannot read) is refused with 422 `unsupported_document_format` before any job starts.

```http
POST /v1/summaries
```

Starts an async summary job for a YouTube video, a web page, or pasted text, selected by the `source` field. Usually responds 202 with a `Location` header and a `job_id` you can poll at GET /v1/jobs/{id} (send an `Idempotency-Key` header to make retries safe). If the exact source was already summarized in the requested language it responds 200 `already_complete` with the `article_id` and no job to poll. A web-page `url` whose path ends in `.doc` (a legacy Word file, which the web-page summarizer cannot read) is refused with 422 `unsupported_document_format` before any job starts.

## Authentication

Requires a Bearer credential — a `shk_live_` API key or an OAuth 2.1 access token with the scope for this resource. See [Authentication](/docs/api).

## Parameters

| Name | In | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | No | Optional client-generated key (1–255 visible ASCII chars) that makes this POST replay-safe: a retry with the SAME key and body returns the original response (with `Idempotency-Replayed: true`) instead of creating a duplicate. Reusing a key with a different body is rejected (422). |

## Request body

### source: "youtube"

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `source` | `"youtube"` | Yes | — |
| `url` | `string<uri>` | Yes | A YouTube video URL. |
| `language` | `string` | No | Language name ("english") or ISO-639-1 code ("en"). Defaults to english. (2–20 chars) Default: "english". |

### source: "url"

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `source` | `"url"` | Yes | — |
| `url` | `string<uri>` | Yes | A web page / article URL to summarize. |
| `language` | `string` | No | Language name ("english") or ISO-639-1 code ("en"). Defaults to english. (2–20 chars) Default: "english". |

### source: "text"

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `source` | `"text"` | Yes | — |
| `content` | `string` | Yes | The raw text to summarize. |
| `title` | `string` | No | Optional title hint (reserved — currently derived by the summarizer). |
| `language` | `string` | No | Language name ("english") or ISO-639-1 code ("en"). Defaults to english. (2–20 chars) Default: "english". |

## Example request

curl:

```bash
curl -X POST https://aishorty.com/v1/summaries \
  -H "Authorization: Bearer shk_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "source": "youtube",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  }'
```

TypeScript (@aishorty/sdk):

```typescript
import { Shorty } from '@aishorty/sdk'

const shorty = new Shorty({ apiKey: process.env.SHORTY_API_KEY })

const job = await shorty.summaries.create({
    source: 'youtube',
    url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
})
const done = await shorty.jobs.waitFor(job.job_id)
console.log(done.status, done.output)
```

## Response · 200

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | `"already_complete"` | Yes | Marks a cache hit: this exact source was already summarized, so no new job was started. |
| `article_id` | `string` | Yes | The id of the already-complete article — fetch it at GET /v1/articles/{id}. |

## Errors

On failure this endpoint returns an RFC 9457 problem body. Possible statuses:

- `400`
- `401`
- `403`
- `409`
- `422`
- `429`
- `500`
- `503`

Switch on the problem `code`, not the status. See the [error reference](/docs/api/errors) for every code and how to fix it.

> **Note:** This endpoint honors an `Idempotency-Key` header: a retry with the same key and body replays the original response for 24 hours instead of creating a duplicate job.
