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

# Guia de integração de mídia

> Resolver metadados, enfileirar downloads e consultar jobs pela API pública

O fluxo recomendado separa **resolução** (síncrona) de **download** (assíncrono via worker).

<Warning>
  **YouTube não é suportado.** URLs do YouTube retornam `unsupported_platform`. Veja [Plataformas](/pages/guides/plataformas).
</Warning>

## Fluxo recomendado

<Steps>
  <Step title="Listar plataformas (opcional)">
    `GET /platforms` retorna hosts suportados e capacidades (`video`, `audio`, `image`, `metadata`).
  </Step>

  <Step title="Resolver a URL">
    `POST /media/resolve` com `{ "url": "..." }` retorna `data.id`, título, thumbnail e `formats[]`.
  </Step>

  <Step title="Enfileirar download">
    `POST /media/download` com `{ "media_id": "<data.id>", "format": "video_best" }` retorna `202` e `job_id`.
  </Step>

  <Step title="Consultar job">
    `GET /jobs/{jobId}` até `status: "completed"` — então use `result.download_url`.
  </Step>
</Steps>

## Exemplos completos

<CodeGroup>
  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  // Requer SHAPPIRE_API_KEY em process.env
  import { resolveMedia, enqueueDownload, waitForJob } from './shappire.js';

  const url = 'https://www.tiktok.com/@user/video/7123456789012345678';

  const media = await resolveMedia(url);
  const format = media.formats.find((f) => f.id === 'video_best')?.id ?? 'video_best';
  const jobId = await enqueueDownload(media.id, format);
  const job = await waitForJob(jobId);

  console.log(job.result.download_url);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os
  # Requer SHAPPIRE_API_KEY em os.environ
  url = "https://www.tiktok.com/@user/video/7123456789012345678"

  media = resolve_media(url)
  job_id = enqueue_download(media["id"], "video_best")
  job = wait_for_job(job_id)

  print(job["result"]["download_url"])
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  media, err := ResolveMedia("https://www.tiktok.com/@user/video/7123456789012345678")
  if err != nil {
  	log.Fatal(err)
  }

  mediaID, _ := media["id"].(string)
  jobID, err := EnqueueDownload(mediaID, "video_best")
  if err != nil {
  	log.Fatal(err)
  }

  job, err := WaitForJob(jobID)
  if err != nil {
  	log.Fatal(err)
  }
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # 1. Resolver
  MEDIA=$(curl -s https://api.shappire.tools/v1/media/resolve \
    -H "X-API-Key: $SHAPPIRE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"url":"https://www.tiktok.com/@user/video/7123456789012345678"}')

  MEDIA_ID=$(echo "$MEDIA" | jq -r '.data.id')

  # 2. Enfileirar
  JOB=$(curl -s -X POST https://api.shappire.tools/v1/media/download \
    -H "X-API-Key: $SHAPPIRE_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"media_id\":\"$MEDIA_ID\",\"format\":\"video_best\"}")

  JOB_ID=$(echo "$JOB" | jq -r '.data.job_id')

  # 3. Polling
  curl https://api.shappire.tools/v1/jobs/$JOB_ID \
    -H "X-API-Key: $SHAPPIRE_API_KEY"
  ```
</CodeGroup>

## Resolver sem download prévio

Você pode enviar `url` diretamente em `POST /media/download`, mas resolver antes evita reprocessamento e permite exibir metadados no seu UI antes do download.

## Campo `id` vs `media_id`

| Contexto            | Campo      | Exemplo                  |
| ------------------- | ---------- | ------------------------ |
| Resposta do resolve | `data.id`  | `med_a1b2c3d4`           |
| Request do download | `media_id` | mesmo valor de `data.id` |

TTL padrão do resolve: **1 hora** (`API_MEDIA_RESOLVE_TTL_SECONDS=3600`). Após expirar, `media_not_found`.

## Formatos

| Campo       | Descrição                                                                |
| ----------- | ------------------------------------------------------------------------ |
| `id`        | Identificador para `format` no download (ex. `video_best`, `audio_best`) |
| `type`      | `video`, `audio` ou `image`                                              |
| `quality`   | Qualidade reportada pelo engine                                          |
| `container` | Extensão esperada (`mp4`, `mp3`, …)                                      |

## Estados do job

| Status       | Significado                      |
| ------------ | -------------------------------- |
| `queued`     | Aguardando worker                |
| `processing` | Download em andamento            |
| `completed`  | `result.download_url` disponível |
| `failed`     | Ver `error.code` no corpo        |

Se o job expirar (TTL padrão 1h), `GET /jobs/{jobId}` retorna `404 job_not_found` — enfileire novamente.

## Por linguagem

* [JavaScript](/pages/guides/exemplos-javascript)
* [Python](/pages/guides/exemplos-python)
* [Go](/pages/guides/exemplos-go)
* [PHP](/pages/guides/exemplos-php)
* [Ruby](/pages/guides/exemplos-ruby)
* [Java](/pages/guides/exemplos-java)

Tutoriais: [TikTok](/tutorials/tiktok-download) · [Instagram](/tutorials/instagram-download) · [Áudio](/tutorials/extrair-audio) · [Plataformas](/pages/guides/plataformas)
