> ## 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.

# Exemplos por linguagem

> Integração completa em JavaScript, Python, Go, PHP, Ruby, Java e cURL

A Shappire Media API é HTTP/JSON — funciona em qualquer linguagem. Abaixo estão os fluxos principais com exemplos prontos para copiar.

<Info>
  Defina `SHAPPIRE_API_KEY` no ambiente. Nunca exponha a chave no frontend.
</Info>

## Listar plataformas

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl https://api.shappire.tools/v1/platforms \
    -H "X-API-Key: $SHAPPIRE_API_KEY"
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const res = await fetch('https://api.shappire.tools/v1/platforms', {
    headers: { 'X-API-Key': process.env.SHAPPIRE_API_KEY },
  });
  const { data } = await res.json();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os, requests
  r = requests.get(
      "https://api.shappire.tools/v1/platforms",
      headers={"X-API-Key": os.environ["SHAPPIRE_API_KEY"]},
  )
  platforms = r.json()["data"]
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  req, _ := http.NewRequest("GET", baseURL+"/platforms", nil)
  req.Header.Set("X-API-Key", os.Getenv("SHAPPIRE_API_KEY"))
  ```
</CodeGroup>

## Resolver mídia

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl 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"}'
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const API_KEY = process.env.SHAPPIRE_API_KEY;
  const BASE = 'https://api.shappire.tools/v1';

  export async function resolveMedia(url) {
    const res = await fetch(`${BASE}/media/resolve`, {
      method: 'POST',
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ url }),
    });

    if (!res.ok) {
      const err = await res.json();
      throw new Error(err.error?.message ?? res.statusText);
    }

    const { data } = await res.json();
    return data;
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os
  import requests

  API_KEY = os.environ["SHAPPIRE_API_KEY"]
  BASE = "https://api.shappire.tools/v1"

  def resolve_media(url: str) -> dict:
      response = requests.post(
          f"{BASE}/media/resolve",
          headers={"X-API-Key": API_KEY},
          json={"url": url},
          timeout=30,
      )
      response.raise_for_status()
      return response.json()["data"]
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  package shappire

  import (
  	"bytes"
  	"encoding/json"
  	"fmt"
  	"net/http"
  	"os"
  )

  const baseURL = "https://api.shappire.tools/v1"

  type resolveResponse struct {
  	Data map[string]interface{} `json:"data"`
  }

  func ResolveMedia(url string) (map[string]interface{}, error) {
  	body, _ := json.Marshal(map[string]string{"url": url})
  	req, err := http.NewRequest(http.MethodPost, baseURL+"/media/resolve", bytes.NewReader(body))
  	if err != nil {
  		return nil, err
  	}
  	req.Header.Set("X-API-Key", os.Getenv("SHAPPIRE_API_KEY"))
  	req.Header.Set("Content-Type", "application/json")

  	resp, err := http.DefaultClient.Do(req)
  	if err != nil {
  		return nil, err
  	}
  	defer resp.Body.Close()

  	if resp.StatusCode >= 400 {
  		return nil, fmt.Errorf("resolve failed: %s", resp.Status)
  	}

  	var out resolveResponse
  	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
  		return nil, err
  	}
  	return out.Data, nil
  }
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  <?php

  $apiKey = getenv('SHAPPIRE_API_KEY');
  $base = 'https://api.shappire.tools/v1';

  function resolveMedia(string $url): array {
      global $apiKey, $base;

      $ch = curl_init("$base/media/resolve");
      curl_setopt_array($ch, [
          CURLOPT_POST => true,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_HTTPHEADER => [
              "X-API-Key: $apiKey",
              'Content-Type: application/json',
          ],
          CURLOPT_POSTFIELDS => json_encode(['url' => $url]),
      ]);

      $body = curl_exec($ch);
      $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);

      if ($status >= 400) {
          throw new RuntimeException("resolve failed ($status): $body");
      }

      return json_decode($body, true)['data'];
  }
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  require 'net/http'
  require 'json'

  API_KEY = ENV.fetch('SHAPPIRE_API_KEY')
  BASE = 'https://api.shappire.tools/v1'

  def resolve_media(url)
    uri = URI("#{BASE}/media/resolve")
    req = Net::HTTP::Post.new(uri)
    req['X-API-Key'] = API_KEY
    req['Content-Type'] = 'application/json'
    req.body = { url: url }.to_json

    res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
    raise res.body unless res.is_a?(Net::HTTPSuccess)

    JSON.parse(res.body)['data']
  end
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  public class ShappireClient {
    private static final String BASE = "https://api.shappire.tools/v1";
    private final String apiKey;
    private final HttpClient client = HttpClient.newHttpClient();

    public ShappireClient(String apiKey) {
      this.apiKey = apiKey;
    }

    public String resolveMedia(String url) throws Exception {
      String body = String.format("{\"url\":\"%s\"}", url);
      HttpRequest request = HttpRequest.newBuilder()
          .uri(URI.create(BASE + "/media/resolve"))
          .header("X-API-Key", apiKey)
          .header("Content-Type", "application/json")
          .POST(HttpRequest.BodyPublishers.ofString(body))
          .build();

      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      if (response.statusCode() >= 400) {
        throw new RuntimeException("resolve failed: " + response.body());
      }
      return response.body();
    }
  }
  ```
</CodeGroup>

## Enfileirar download

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST https://api.shappire.tools/v1/media/download \
    -H "X-API-Key: $SHAPPIRE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"media_id":"med_abc123","format":"video_best"}'
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const API_KEY = process.env.SHAPPIRE_API_KEY;
  const BASE = 'https://api.shappire.tools/v1';

  export async function enqueueDownload(mediaId, format) {
    const res = await fetch(`${BASE}/media/download`, {
      method: 'POST',
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ media_id: mediaId, format }),
    });

    if (res.status !== 202) {
      const err = await res.json();
      throw new Error(err.error?.message ?? res.statusText);
    }

    const { data } = await res.json();
    return data.job_id;
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os
  import requests

  API_KEY = os.environ["SHAPPIRE_API_KEY"]
  BASE = "https://api.shappire.tools/v1"

  def enqueue_download(media_id: str, format: str) -> str:
      response = requests.post(
          f"{BASE}/media/download",
          headers={"X-API-Key": API_KEY},
          json={"media_id": media_id, "format": format},
          timeout=30,
      )
      response.raise_for_status()
      return response.json()["data"]["job_id"]
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  func EnqueueDownload(mediaID, format string) (string, error) {
  	body, _ := json.Marshal(map[string]string{
  		"media_id": mediaID,
  		"format":   format,
  	})
  	req, err := http.NewRequest(http.MethodPost, baseURL+"/media/download", bytes.NewReader(body))
  	if err != nil {
  		return "", err
  	}
  	req.Header.Set("X-API-Key", os.Getenv("SHAPPIRE_API_KEY"))
  	req.Header.Set("Content-Type", "application/json")

  	resp, err := http.DefaultClient.Do(req)
  	if err != nil {
  		return "", err
  	}
  	defer resp.Body.Close()

  	var out struct {
  		Data struct {
  			JobID string `json:"job_id"`
  		} `json:"data"`
  	}
  	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
  		return "", err
  	}
  	return out.Data.JobID, nil
  }
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  function enqueueDownload(string $mediaId, string $format): string {
      global $apiKey, $base;

      $ch = curl_init("$base/media/download");
      curl_setopt_array($ch, [
          CURLOPT_POST => true,
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_HTTPHEADER => [
              "X-API-Key: $apiKey",
              'Content-Type: application/json',
          ],
          CURLOPT_POSTFIELDS => json_encode([
              'media_id' => $mediaId,
              'format' => $format,
          ]),
      ]);

      $body = curl_exec($ch);
      curl_close($ch);
      return json_decode($body, true)['data']['job_id'];
  }
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  def enqueue_download(media_id, format)
    uri = URI("#{BASE}/media/download")
    req = Net::HTTP::Post.new(uri)
    req['X-API-Key'] = API_KEY
    req['Content-Type'] = 'application/json'
    req.body = { media_id: media_id, format: format }.to_json

    res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
    JSON.parse(res.body)['data']['job_id']
  end
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  public String enqueueDownload(String mediaId, String format) throws Exception {
    String body = String.format(
        "{\"media_id\":\"%s\",\"format\":\"%s\"}", mediaId, format);
    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(BASE + "/media/download"))
        .header("X-API-Key", apiKey)
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    return response.body();
  }
  ```
</CodeGroup>

## Consultar job (polling)

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl https://api.shappire.tools/v1/jobs/job_xyz789 \
    -H "X-API-Key: $SHAPPIRE_API_KEY"
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const API_KEY = process.env.SHAPPIRE_API_KEY;
  const BASE = 'https://api.shappire.tools/v1';

  export async function waitForJob(jobId, { intervalMs = 3000, timeoutMs = 300000 } = {}) {
    const started = Date.now();

    while (Date.now() - started < timeoutMs) {
      const res = await fetch(`${BASE}/jobs/${jobId}`, {
        headers: { 'X-API-Key': API_KEY },
      });
      const { data } = await res.json();

      if (data.status === 'completed') return data;
      if (data.status === 'failed') throw new Error(data.error?.message ?? 'job failed');

      await new Promise((r) => setTimeout(r, intervalMs));
    }

    throw new Error('job timeout');
  }
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import time

  def wait_for_job(job_id: str, interval: float = 3.0, timeout: float = 300.0) -> dict:
      started = time.time()
      while time.time() - started < timeout:
          response = requests.get(
              f"{BASE}/jobs/{job_id}",
              headers={"X-API-Key": API_KEY},
              timeout=30,
          )
          response.raise_for_status()
          data = response.json()["data"]

          if data["status"] == "completed":
              return data
          if data["status"] == "failed":
              raise RuntimeError(data.get("error", {}).get("message", "job failed"))

          time.sleep(interval)

      raise TimeoutError("job timeout")
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  func WaitForJob(jobID string) (map[string]interface{}, error) {
  	for {
  		req, _ := http.NewRequest(http.MethodGet, baseURL+"/jobs/"+jobID, nil)
  		req.Header.Set("X-API-Key", os.Getenv("SHAPPIRE_API_KEY"))

  		resp, err := http.DefaultClient.Do(req)
  		if err != nil {
  			return nil, err
  		}
  		defer resp.Body.Close()

  		var out struct {
  			Data map[string]interface{} `json:"data"`
  		}
  		json.NewDecoder(resp.Body).Decode(&out)

  		status, _ := out.Data["status"].(string)
  		switch status {
  		case "completed":
  			return out.Data, nil
  		case "failed":
  			return nil, fmt.Errorf("job failed")
  		}

  		time.Sleep(3 * time.Second)
  	}
  }
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  function waitForJob(string $jobId, int $timeoutSeconds = 300): array {
      global $apiKey, $base;
      $started = time();

      while (time() - $started < $timeoutSeconds) {
          $ch = curl_init("$base/jobs/$jobId");
          curl_setopt_array($ch, [
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_HTTPHEADER => ["X-API-Key: $apiKey"],
          ]);
          $body = curl_exec($ch);
          curl_close($ch);

          $data = json_decode($body, true)['data'];
          if ($data['status'] === 'completed') return $data;
          if ($data['status'] === 'failed') throw new RuntimeException('job failed');

          sleep(3);
      }

      throw new RuntimeException('job timeout');
  }
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  def wait_for_job(job_id, interval: 3, timeout: 300)
    started = Time.now
    loop do
      uri = URI("#{BASE}/jobs/#{job_id}")
      req = Net::HTTP::Get.new(uri)
      req['X-API-Key'] = API_KEY
      res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
      data = JSON.parse(res.body)['data']

      return data if data['status'] == 'completed'
      raise 'job failed' if data['status'] == 'failed'
      raise 'job timeout' if Time.now - started > timeout

      sleep interval
    end
  end
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  public String getJob(String jobId) throws Exception {
    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create(BASE + "/jobs/" + jobId))
        .header("X-API-Key", apiKey)
        .GET()
        .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    return response.body();
  }
  ```
</CodeGroup>

## Fluxo completo

<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>

## Guias por linguagem

<Columns cols={2}>
  <Card title="JavaScript / Node.js" icon="braces" href="/pages/guides/exemplos-javascript">
    fetch, axios e worker
  </Card>

  <Card title="Python" icon="file-code" href="/pages/guides/exemplos-python">
    requests e asyncio
  </Card>

  <Card title="Go" icon="box" href="/pages/guides/exemplos-go">
    net/http e context
  </Card>

  <Card title="PHP" icon="code" href="/pages/guides/exemplos-php">
    curl e Laravel
  </Card>

  <Card title="Ruby" icon="gem" href="/pages/guides/exemplos-ruby">
    Net::HTTP e Sidekiq
  </Card>

  <Card title="Java" icon="coffee" href="/pages/guides/exemplos-java">
    HttpClient e Spring
  </Card>
</Columns>
