View the package on npm · Open Genie Dashboard
1. Install
Use Node.js 20 or later. Server API access requires a paid plan or an active trial.
npm install @genie-player/node2. Create a server API key
In Dashboard → API keys, select your project and create a server key. Store it as GENIE_PLAYER_API_KEY in your backend environment. Keep it out of browser code and logs.
3. Upload and receive captions
import { GeniePlayer } from "@genie-player/node";
const genie = new GeniePlayer({
apiKey: process.env.GENIE_PLAYER_API_KEY!,
});
const { job, captions, captionUrls } = await genie.media.processAndDownload({
file: "./lesson.mp4",
targetLanguages: ["es", "ja"],
});
console.log(job.status); // READY
console.log(captions.es); // Spanish WebVTT text
console.log(captionUrls.es); // Signed download URL, valid for one hourThe client uploads, waits for completion, and downloads the requested captions. Genie removes the temporary source video when an SDK job finishes; retain your own video for playback.
4. Receive a webhook instead
In Dashboard → Webhooks, save your HTTPS receiver URL and select the events to receive. Copy the endpoint signing secret into your server environment as GENIE_ENDPOINT_WEBHOOK_SECRET. Submit a job without waiting:
const { job } = await genie.media.createAndTranslate({
file: "./lesson.mp4",
targetLanguages: ["es"],
});Omitting webhookUrl uses the project endpoint. Verify the original request bytes before JSON parsing:
import { verifyGenieWebhook } from "@genie-player/node";
const event = verifyGenieWebhook(
rawBody,
headers,
process.env.GENIE_ENDPOINT_WEBHOOK_SECRET!,
);
if (event.type === "translation_job.completed") {
// Queue a background task to download event.tracks[].downloadUrl.
}Return 2xx promptly after accepting an event and deduplicate by event.id. Use Send test for a signed webhook.test event, and inspect attempts in delivery history.
5. Run a webhook receiver
Save this as receiver.mjs, set your endpoint secret, and run node receiver.mjs. Route a public HTTPS endpoint to this server and configure that URL in the dashboard.
import { createServer } from "node:http";
import { verifyGenieWebhook } from "@genie-player/node";
const secret = process.env.GENIE_ENDPOINT_WEBHOOK_SECRET;
if (!secret) throw new Error("Set GENIE_ENDPOINT_WEBHOOK_SECRET");
createServer(async (request, response) => {
if (request.method !== "POST" || request.url !== "/webhooks/genie") {
response.writeHead(404).end();
return;
}
try {
const chunks = [];
let size = 0;
for await (const chunk of request) {
size += chunk.length;
if (size > 256 * 1024) {
response.writeHead(413).end();
return;
}
chunks.push(chunk);
}
const event = verifyGenieWebhook(
Buffer.concat(chunks), request.headers, secret,
);
console.log("Verified event:", event.id, event.type);
// In production, persist/deduplicate event.id and queue work before acknowledging.
response.writeHead(204).end();
} catch {
response.writeHead(400).end();
}
}).listen(3000);Click Send test and look for webhook.test in the receiver output. Then submit a video and look for translation_job.completed. Completed events include caption tracks with one-hour signed download URLs. Failed and canceled events have their own event types. Inspect delivery attempts in Dashboard → Webhooks.
An explicit per-job webhookUrl replaces the default and uses the separate secret returned by genie.webhooks.retrieveSigningSecret(). See the Node.js reference for methods and errors.