Pular para o conteúdo

JavaScript, Python e n8n

As receitas usam a API REST e seu próprio segredo. Salve um UUID em INFINITY_FLOW_REQUEST_KEY antes de executar; use o mesmo UUID e payload para retomar depois de uma resposta perdida. Os exemplos fazem trabalho real quando usados com credenciais de produção.

Node com fetch nativo. Não execute este código no navegador:

const base = 'https://infinityflow.stream/api/v1';
const key = process.env.INFINITY_FLOW_API_KEY;
const requestKey = process.env.INFINITY_FLOW_REQUEST_KEY;
if (!key || !requestKey) throw new Error('Configure a chave e um UUID persistido.');
const headers = { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' };
const payload = { prompt: 'Uma floresta ao amanhecer', mediaKind: 'video', aspect: '16:9' };
const response = await fetch(`${base}/generations`, {
method: 'POST',
headers: { ...headers, 'Idempotency-Key': requestKey },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(30000),
});
const result = await response.json();
if (!response.ok) throw new Error(JSON.stringify(result));
const id = result.generation.id; // Persista este ID na sua tarefa.
console.log({ id, state: result.generation.state });
// Repetir GET é seguro. Não repetir POST com outra chave.
for (let attempt = 0; attempt < 120; attempt++) {
await new Promise(resolve => setTimeout(resolve, 5000));
const statusResponse = await fetch(`${base}/generations/${id}`, { headers });
const status = await statusResponse.json();
if (!statusResponse.ok) throw new Error(JSON.stringify(status));
if (status.generation.state === 'succeeded') {
const ticketResponse = await fetch(`${base}/generations/${id}/outputs/0/download-ticket`, { headers });
if (!ticketResponse.ok) throw new Error('Não foi possível obter o download.');
const { url } = await ticketResponse.json();
// Seu download seguinte usa url SEM headers de autenticação do Infinity Flow.
const media = await fetch(url);
if (!media.ok) throw new Error('Link expirou ou download falhou.');
// Grave media.body em seu armazenamento privado. Não registre url nos logs.
break;
}
if (['failed', 'cancelled', 'attention_required'].includes(status.generation.state)) {
console.log({ id, state: status.generation.state });
break;
}
}

Se o loop terminar sem conclusão, mantenha o ID e consulte depois. Um timeout local não cancela nem recria o pedido. Em uma aplicação real, implemente backoff e persistência da tarefa.

import json, os, urllib.request
base = 'https://infinityflow.stream/api/v1'
key = os.environ['INFINITY_FLOW_API_KEY']
request_key = os.environ['INFINITY_FLOW_REQUEST_KEY'] # UUID salvo antes de executar
payload = {'prompt': 'Uma floresta ao amanhecer', 'mediaKind': 'video', 'aspect': '16:9'}
request = urllib.request.Request(
base + '/generations',
data=json.dumps(payload).encode(),
headers={'Authorization': 'Bearer ' + key,
'Content-Type': 'application/json',
'Idempotency-Key': request_key},
method='POST',
)
with urllib.request.urlopen(request, timeout=30) as response:
generation = json.load(response)['generation']
print({'id': generation['id'], 'state': generation['state']})
# Salve generation['id']; consulte GET /generations/{id} para acompanhar.
# Em timeout, conserve request_key/payload. Não gere outro UUID automaticamente.
  1. Na origem da tarefa, persista requestKey UUID e o payload. Não use um UUID recalculado a cada retry ou o ID de execução como substituto do UUID.
  2. Crie uma credencial Header Auth para Authorization: Bearer ... no n8n; não escreva o segredo em campos exportáveis do workflow.
  3. No HTTP Request, use POST https://infinityflow.stream/api/v1/generations, JSON e Idempotency-Key: {{$json.requestKey}}. Mapeie prompt, mediaKind e aspect dos dados persistidos.
  4. Grave generation.id na tarefa antes do próximo passo.
  5. Use Wait e GET /generations/{id} para polling. succeeded segue para download; attention_required, failed e cancelled seguem para acompanhamento, sem novo POST automático.
  6. Obtenha download-ticket autenticado. Baixe a URL em outro HTTP Request sem credencial Header Auth, salvando o arquivo binário antes de expirar.

Se habilitar retry do nó de criação, confirme que ele conserva o mesmo header de idempotência e o mesmo body. Nunca conecte o ramo de erro a um nó que cria outra chave para o mesmo pedido.