Guias rápidos

Node.js

Liste, crie e edite roteiros com o fetch nativo do Node.js.

Pré-requisitos

  • Node.js 18 ou superior (o fetch já vem embutido).
  • Uma chave de API com leitura e escrita, disponível em LIVETP_API_KEY.

1. Crie um cliente

O LiveTP não exige SDK: um pequeno wrapper resolve autenticação e erros.

livetp.ts
const BASE_URL = "https://livetp.app/api/v1";

export async function livetp<T>(path: string, init: RequestInit = {}): Promise<T> {
  const response = await fetch(`${BASE_URL}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.LIVETP_API_KEY}`,
      "Content-Type": "application/json",
      ...init.headers,
    },
  });
  const data = await response.json();
  if (!response.ok) {
    // Formato padrão: { error: { code, message, details? } }
    throw Object.assign(new Error(data.error.message), {
      status: response.status,
      code: data.error.code,
      details: data.error.details,
    });
  }
  return data as T;
}

2. Crie um roteiro

import { livetp } from "./livetp";

const { script } = await livetp<{ script: Script }>("/scripts", {
  method: "POST",
  body: JSON.stringify({
    id: crypto.randomUUID(), // permite repetir a chamada sem duplicar
    title: "Episódio 12",
    content: "Bem-vindos a mais um episódio...",
    status: "draft",
  }),
});

console.log(script.id, script.revision); // revision === 1

3. Liste a biblioteca

const { scripts, hasMore, nextOffset } = await livetp<{
  scripts: Script[];
  hasMore: boolean;
  nextOffset: number | null;
}>("/scripts/library?status=ready&limit=20");

4. Edite sem perder alterações

Toda edição informa a revisão que você leu. Se o roteiro mudou nesse meio-tempo, a API responde 409 e devolve a versão atual em error.details.current.

async function markAsReady(id: string) {
  const { script } = await livetp<{ script: Script }>(`/scripts/${id}`);
  try {
    return await livetp<{ script: Script }>(`/scripts/${id}`, {
      method: "PUT",
      body: JSON.stringify({
        title: script.title,
        content: script.content,
        status: "ready",
        expectedRevision: script.revision,
      }),
    });
  } catch (error) {
    if ((error as { code?: string }).code === "conflict") {
      // Releia e decida com o usuário; nunca sobrescreva automaticamente.
    }
    throw error;
  }
}
types.ts
type Script = {
  id: string;
  title: string;
  content: string;
  status: "draft" | "ready" | "review" | "completed";
  revision: number;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
};

Próximos passos