Generating assets
One call
Section titled “One call”const run = await layer.inferences.generate({ prompt: 'a crystal sword icon, transparent background', batch_size: 4,})
for (const asset of run.outputs ?? []) { console.log(asset.url, asset.content_type, asset.width, asset.height)}generate() submits the run and polls until it finishes, honouring the interval the server asks for. It throws if the run ends in any state other than complete.
Other modalities are the same call with different parameters:
await layer.inferences.generate({ prompt: 'camera pushes through the gate', duration_seconds: 5 })await layer.inferences.generate({ prompt: 'weathered treasure chest, game-ready', modality: 'three_d' })await layer.inferences.generate({ prompt: 'arcade coin pickup', modality: 'audio' })Choosing a model
Section titled “Choosing a model”Leave base_model_id off and Layer picks the recommended model for the modality. To choose deliberately, read the catalogue — which models a workspace can run depends on its plan and its policy, so it is never safe to hard-code an id:
for await (const model of layer.baseModels.listAll({ modality: 'video' })) { console.log(model.base_model_id, model.name)}
const defaults = await layer.baseModels.defaults()const preferred = defaults.featured_by_modality['image']?.[0]A model’s own parameters are described by its schema. Validate against it before submitting: a key a model does not know is dropped, and the run comes back generated from defaults instead of failing.
const schema = await layer.baseModels.inferenceSchema('bfl-flux-2-pro')Pricing before spending
Section titled “Pricing before spending”Generations consume Creative Units, and balance is not checked when a run is submitted — an underfunded run is accepted and then fails. Price it first:
const estimate = await layer.inferences.estimate({ prompt: '…' })
if (!estimate.has_sufficient_creative_units) { throw new Error(`Needs ${estimate.estimated_price_creative_units} CU`)}Or put a ceiling on a single call. Nothing is submitted when it trips:
await layer.inferences.generate({ prompt: '…' }, { maxCreativeUnits: 8 })Pricing runs through the same model selection the run will use, so the ceiling is checked against what the run actually costs — including for an auto-picked model.
Long runs
Section titled “Long runs”For a render you do not want to hold a process open for, submit and collect later:
const accepted = await layer.inferences.create({ prompt: '…', duration_seconds: 10 })// … store accepted.inference_id, come back to it …const run = await layer.inferences.get(accepted.inference_id)wait() is the polling half on its own, and reports progress as it goes:
const run = await layer.inferences.wait(accepted.inference_id, { timeoutMs: 10 * 60 * 1000, onProgress: (state) => console.error(state.status),})Both take an AbortSignal, so a run can be abandoned with the rest of a request:
await layer.inferences.generate({ prompt: '…' }, { signal: request.signal })To stop the run itself rather than stop waiting for it, cancel it:
await layer.inferences.cancel(accepted.inference_id)Reference files
Section titled “Reference files”Uploads go straight to storage rather than through the API, so a large file never crosses the server:
import { readFile } from 'node:fs/promises'
const uploaded = await layer.files.upload(await readFile('hero.png'), { contentType: 'image/png', fileName: 'hero.png',})
await layer.inferences.generate({ prompt: 'the same hero, mid-swing', guidance_files: [{ file_id: uploaded.file_id, type: 'init_image' }],})Which guidance types a model accepts is in its capabilities; see files & uploads for the allowed types and size limits.
Trained styles
Section titled “Trained styles”A reference set — a trained subject, style, or character — is applied by id, alongside or instead of a base model:
await layer.inferences.generate({ prompt: 'a market stall in our house style', reference_sets: [{ reference_set_id: '…' }],})