---
title: "Seal a schedule before the run: the public half, and the secret to you alone."
method: POST
path: "/api/agents/run/pull_seal"
tags: ["Lab"]
---

# Seal a schedule before the run: the public half, and the secret to you alone.

`POST /api/agents/run/pull_seal`

## Request

- Base URL: `https://tomorrowlives.com`
- URL: `https://tomorrowlives.com/api/agents/run/pull_seal`
- Auth: HTTP bearer

Seals a schedule's text before the run: commits to it (SHA-256 of the text and a nonce) and encrypts it (ChaCha20) under a fresh key. Answers with sealed (the public half, for the session's schedule.sealed) and secret (the key, IV and nonce), to this call alone: this service does not store, log or show again either the text or the secret, so keep the secret, release each cue at its moment, and publish the secret into the session's schedule.opened after the close. held_by names the leader station's generator (default L); at_ns is when it was sealed, before start_ns. By default the randomness is 32 bytes of this server's operating-system randomness, graded hardware_seeded; seed draws from software instead (graded software, which a research run refuses); entropy_hex with grade brings your own bytes and says where they came from. Costs 1 unit.

## Request body

- object
  - `content` string, required: The schedule text to seal, as drawn by pull_schedule.
  - `held_by` string: Who holds the secret half, recorded with the seal.
  - `at_ns` integer: The sealing time in integer nanoseconds.
  - `entropy` 'os': The entropy source: os, the server's own.
  - `seed` integer: A whole number that makes the run reproducible: the same seed and inputs give the same answer.
  - `entropy_hex` string: Your own entropy as hex, in place of the server's, when you must bring the bytes yourself; grade then says where they came from.
  - `grade` 'true_random' | 'hardware_seeded' | 'physical_noise' | 'software': How the entropy you brought was produced, recorded with the schedule.

## Response `200`

The job's result and files

- Job
  - `job` string
  - `verb` string
  - `units` integer
  - `ms` integer
  - `result` unknown
  - `files` object[]
    - `name` string
    - `bytes` integer
    - `content_type` string
    - `url` string
    - `url_expires_at` string, date-time

## Other responses

- `400`: The input is not valid
- `401`: No valid API key
- `402`: A pass or a payment is needed: a queued render on the free plan, a unit pack on the free plan (pass_required), a card plan's past-due renewal, or, on the free plan, an owner who has not confirmed their email yet (owner_unconfirmed; a pass needs no confirmation); or a payment did not go through (payment_failed, payment_token_unusable), and nothing was charged
- `403`: The account is suspended, the paying card is not from the United States (region_not_supported), or the address named as its owner said it is not theirs and costed runs are paused until a new owner is named (owner_removed)
- `413`: The input or the output is over its cap; a job stopped by the output cap is not charged
- `422`: The engine refused the input, a limit of the service's refused it (error: video_limit or pull_limit) or stopped the job, or the content policy refused the input (error: content_policy)
- `429`: A limit was hit; reset_at says when it lifts (also in Retry-After)
- `503`: The engines are busy or not installed
- `504`: The job ran past its time and was stopped

---

[API](https://skmtc.dev/tomorrowlives/apis/tomorrow-lives-engines.md) · [All operations](https://skmtc.dev/tomorrowlives/apis/tomorrow-lives-engines/llms.txt) · [OpenAPI document](https://skmtc.dev/tomorrowlives/apis/tomorrow-lives-engines/revisions/afc3d67322ac?raw)
