Introduction
The Admin API lets you manage regular API keys and inspect billing data for a personal account or organization. Organization admin keys also provide access to container-related APIs. Personal admin keys access only the creator’s personal resources, even if the creator belongs to an organization. Organization admin keys access only their organization. Select Personal or the target organization in the dashboard before creating a key; organization keys require an admin role in that organization. Creating an admin key requires a signed-in user session, not another admin key. It does not require active API billing, but creating regular inference keys still requires active token billing for the account. Existing personal admin keys remain valid.Common use cases
- Automating key management: Create, rotate, or delete API keys programmatically, and set expiration dates or token limits based on your business logic.
- Building custom dashboards: Display usage metrics, cost breakdowns by model, and historical trends using the billing and time-series endpoints.
- Monitoring usage: Query aggregated or per-key usage statistics to track costs and token consumption.
- Managing containers programmatically: Create, validate, deploy, update, stop, and delete instances. Inspect and update projects, wrap model weights, manage repository config and release builds, and manage org secrets, SSH keys, custom domains, and registry credentials.
Authentication
Admin API keys provide programmatic access to your account resources. Admin keys are prefixed withadmin_ and must be included in the Authorization header as a Bearer token.
Need to create an admin API key? Follow our step-by-step guide: Getting a Tinfoil Admin Key
Available endpoints
This page covers the following endpoints:Caller identity
GET /api/auth/context- Inspect the authenticated personal or organization context
API key management
GET /api/keys- List API keysPOST /api/keys- Create a new API keyPOST /api/keys/update- Update an API key’s name, expiration, limits, or notificationsDELETE /api/keys/:key- Delete an API key
Billing & usage
GET /api/billing/usage- Get aggregated usage statistics for all keysPOST /api/billing/usage/key- Get usage statistics for a specific keyGET /api/billing/time-series- Get time series dataGET /api/billing/transactions- Get transaction history
Container endpoints
- Lifecycle & deployment
POST /api/containers/validate-name- Validate a container name or custom domain before deployPOST /api/containers/validate- Validatetinfoil-config.ymlbefore deployGET /api/containers/hosts- List hosts available to the organizationGET /api/containers- List containersGET /api/containers/:id- Get a specific containerPOST /api/containers- Create a containerPOST /api/containers/:id/update/plan- Preview a running instance’s update without deployingPOST /api/containers/:id/update- Update a running container to a new tag or configurationPOST /api/containers/:id/stop- Stop a running containerPOST /api/containers/:id/deploy- Deploy a stopped or failed containerDELETE /api/containers/:id- Delete a containerGET /api/containers/:id/update- Get in-progress update statusPOST /api/containers/:id/update/promote- Switch traffic to a held update that is readyPOST /api/containers/:id/update/cancel- Cancel an in-progress updatePOST /api/containers/:id/github-connection- Toggle GitHub App connectionGET /api/containers/:id/metrics- Get resource metrics
- Projects
GET /api/containers/projects- List projects with instance countsPATCH /api/containers/projects/:id- Update project settingsPOST /api/containers/projects/:id/update/plan- Preview updates for all or selected instances without deployingPOST /api/containers/projects/:id/update- Update all or selected instances
- Model weights
POST /api/models/wrap- Start a model wrap jobGET /api/models/wrap- List wrap jobsGET /api/models/wrap/:host/:job_id- Get wrap job statusDELETE /api/models/wrap/:host/:job_id- Delete a wrap job
- GitHub repository operations
GET /api/github/repos/:owner/:repo/config- Readtinfoil-config.ymlPOST /api/github/repos/:owner/:repo/config/pr- Open a config pull requestGET /api/github/repos/:owner/:repo/pulls/:number- Get pull request stateGET /api/github/repos/:owner/:repo/build/info- Get release and tag infoGET /api/github/repos/:owner/:repo/build/status- Get release workflow run statusPOST /api/github/repos/:owner/:repo/build- Dispatch a release build
- Related resources
GET /api/secrets- List org secretsPOST /api/secrets- Create an org secretGET /api/secrets/:name- Get a secret’s metadataPUT /api/secrets/:name- Update a secretDELETE /api/secrets/:name- Delete a secretGET /api/repositories/:owner/:repo/secrets- List repository secretsPOST /api/repositories/:owner/:repo/secrets- Create a repository secretGET /api/repositories/:owner/:repo/secrets/:name- Get repository secret metadataPUT /api/repositories/:owner/:repo/secrets/:name- Update a repository secretDELETE /api/repositories/:owner/:repo/secrets/:name- Delete a repository secretGET /api/ssh-keys- List org SSH keysPOST /api/ssh-keys- Create an SSH keyDELETE /api/ssh-keys/:name- Delete an SSH keyGET /api/domains- List custom domainsPOST /api/domains- Add a domainPOST /api/domains/:domain/verify- Verify a domainDELETE /api/domains/:domain- Delete a domainGET /api/registry-credentials- List private registry credential statusPUT /api/registry-credentials/:registry- Create or update private registry credentialsDELETE /api/registry-credentials/:registry- Delete private registry credentials
API Key Management
The response examples in this section use organization admin keys. Personal inference-key responses omitis_owner.
List API Keys
endpoint
Returns regular (non-admin) API keys for the key’s account. Personal admin keys return only the creator’s personal keys, in full. Organization admin keys return all organization keys; keys created by other members are masked (for example,
tk_12345***).Example Request
Response
1000000000 = $1.00).
Create API Key
endpoint
Creates a new regular API key for the admin key’s personal account or organization. Requires active token billing for that account.
Request Body
string
required
Name for the API key. Must contain only alphanumeric characters, hyphens, underscores, spaces, and periods.
datetime
ISO 8601 timestamp when the key should expire. If not provided, the key doesn’t expire.
object
Custom metadata to attach to the key. Maximum size: 5KB.
number
Maximum spend in dollars for this key. Must be at least
0.01. Omit or pass 0 for no cost limit.integer
Maximum input tokens this key can consume. Omit or pass
0 for no limit.integer
Maximum output tokens this key can consume. Omit or pass
0 for no limit.boolean
default:"true"
Whether to email the key owner as any configured cap is approached or reached.
integer
default:"80"
Percentage of a cap at which the warning is sent. Must be between 1 and 100.
429 and code: insufficient_quota. See Quota errors.
Example Request
Response
Update API Key
endpoint
Updates an existing regular API key. Personal admin keys can update only the creator’s personal inference keys. Organization admin keys can update regular keys in their organization. Requires the full key value; admin keys cannot be updated through admin-key authentication.
Request Body
string
required
The API key value to update, as returned by
GET /api/keys.string
New display name for the API key.
datetime | null
New expiration as an RFC 3339 timestamp in the future. Pass
null to make the key non-expiring. Omit to leave it unchanged.number
New spend cap in dollars. Set this to
0 to clear the existing cap.integer
New input token cap. Set this to
0 to clear the existing cap.integer
New output token cap. Set this to
0 to clear the existing cap.boolean
Whether to email the key owner as any configured cap is approached or reached.
integer
Percentage of a cap at which the warning is sent. Must be between 1 and 100.
Example Request
Response
Delete API Key
endpoint
Deletes a regular API key. Personal admin keys can delete only the creator’s personal inference keys. Organization admin keys can delete regular keys in their organization. Requires the full key value; admin keys cannot be deleted through admin-key authentication.
Path Parameters
string
required
The API key value to delete (for example,
tk_your_full_key_value_here).Example Request
Response
Billing & Usage
Get Usage Statistics
endpoint
Retrieves aggregated usage statistics for the admin key’s personal account or organization for the specified time period.
Query Parameters
string
Time preset for usage statistics. If omitted, returns all-time usage. Valid values:
5m, 15m, 30m, 1h, 24h, today, 7d, 30d, 60d, 90d, 180d, 365d, 3mo, 6mo, 12mo, all, and period (the account’s current token billing period).datetime
RFC 3339 start of an explicit range. Must be paired with
end. Takes precedence over time.datetime
RFC 3339 end of an explicit range. Must be paired with
start. Future values are clamped to now. The range cannot exceed two years.Example Request
Response
keys object is grouped by API key name. cached_input_tokens counts the subset of input_tokens served from prompt cache.
Get Usage by Key
endpoint
Retrieves usage statistics for a specific regular API key in the admin key’s personal account or organization.
Query Parameters
Accepts the sametime, start, and end parameters as GET /api/billing/usage. If omitted, returns all-time usage.
Request Body
string
required
The API key value to query (for example,
tk_your_full_key_value_here), as returned by GET /api/keys.Example Request
Response
Get Time Series Data
endpoint
Retrieves time-series usage data for the admin key’s personal account or organization over the specified period.
Query Parameters
string
default:"24h"
Time preset for the time series. Accepts the same presets as
GET /api/billing/usage, including period. Explicit start and end parameters are also supported.5m → 5s, 15m → 15s, 30m → 30s, 1h → 1m, 24h → 15m, 7d → 2h, 30d → 8h, 365d → 24h, and longer ranges → 168h. Empty buckets are included as zero-value data points.
Example Request
Response
Get Transaction History
endpoint
Retrieves invoice and standalone charge history for the admin key’s personal account or organization.
Example Request
Response
Authenticated context
GET /api/auth/context returns the effective caller identity without listing organization resources. It is available to authenticated organization and personal admin keys, including scoped keys without container-host permissions. The CLI uses it for login and whoami.
The response contains user_id, context_type (organization or personal), and organization: an object containing id for organization context, or null for personal context. It does not return secret key material or an organization name. Use the returned context rather than inferring an organization from the key string.
Containers
Organization admin API keys can access the same container APIs as a browser session, as long as the key belongs to the target organization. Personal admin keys cannot access these organization-only resources.Create, deploy, and update operations require an active container subscription. Read-only endpoints and cleanup operations such as list, get, stop, and delete do not require an active subscription.
Private registry endpoints require private registry access to be enabled for the organization.
Scoped admin keys
Scoped admin keys use route action names in theirallowed_actions list. The public container-related actions are:
Container restrictions can set allowed
owner/repo values and a container-name regular expression. Container lists return only matches, while reads and lifecycle operations reject nonmatching containers. Creates check the requested repository and name. A create request with replace_container_id also requires containers.delete access to the container being replaced.
The CLI performs auxiliary requests. Creating an instance requires containers.validate as well as containers.create: the CLI validates the configuration and mount assignments before creating anything. It sends the proposed name as instance_name, so name-restricted keys can validate a matching create without gaining access to other names. Container commands that resolve an ID or name require containers.read in addition to the operation’s action; name resolution uses the container list. Project get, settings, and update commands resolve through the project list and therefore require containers.projects.read. Update planning uses the same action permission as the corresponding update. tinfoil login and tinfoil whoami use authenticated context, not the hosts route.
Repository-level operations cannot always narrow access to one container name. Project routes are visible or allowed only when the repository matches and every existing instance matches the name restriction. Repository-secret and GitHub repository operations reject name-restricted keys. A key with any container repository or name restriction is also denied organization-wide container runtime status, organization secrets, SSH keys, custom domains, registry credentials, and model weights, even if containers.runtime-status.read, secrets.read, secrets.write, ssh-keys.read, ssh-keys.write, domains.read, domains.write, registry-credentials.read, registry-credentials.write, or any models.* action is listed.
Some endpoints have no action name and are reachable only by unscoped admin keys. A scoped key receives 403 Forbidden on all API key management routes (/api/keys), on the billing usage, time-series, and transaction routes, and on POST /api/containers/validate-name. Use an unscoped admin key for key management and billing automation.
Lifecycle & Deployment
Validate Container Name
endpoint
Checks whether a container name is valid and available for the current organization. You can also validate a custom domain before creating or updating a container.
Request Body
string
required
Container name. Must be lowercase alphanumeric with hyphens, max 64 characters.
boolean
Whether to validate the name for debug mode.
string
Custom domain to validate.
string
Existing container UUID when validating an update that keeps the same custom domain.
Example Request
Response
Validate Container Config
endpoint
Validates the
tinfoil-config.yml in a repository tag before create, replace, or update.Request Body
string
required
GitHub repository in
owner/repo format.string
required
Git tag to validate.
string
Proposed name when validating a new instance. Required for a name-restricted
admin key when no existing instance ID is supplied. The name and repository
must both match the key’s restrictions. For update or replacement validation,
authorization uses the existing instance’s stored name and ownership, not this
proposed name.
string
Existing container UUID. When present, instance-limit checks are skipped for update validation.
string
Existing container UUID. When present, instance-limit checks are skipped for replace validation.
List Hosts
endpoint
Returns only hosts surfaced to the organization. If a default host is
returned, it is marked
is_default. Each host’s available_gpu_values is
the intersection of the host’s capabilities and the organization’s GPU
entitlement.Response
List Containers
endpoint
Returns all containers in your organization. Responses may also include
ssh_port, host_name, host_gpu_type, and host_cpu_type when available.Example Request
Response
Thecpus, memory_mb, and gpus response fields report the resources from
the measured tinfoil-config.yml in the published release. Lifecycle request
bodies do not override these resources.
Get Container
endpoint
Returns details for a specific container.
Path Parameters
string
required
The container UUID.
Example Request
Create Container
endpoint
Creates a new instance and deploys it unless the config declares volume mounts. The repository must contain a
tinfoil-config.yml at the specified tag.Request Body
string
required
Container name. Must be lowercase alphanumeric with hyphens.
string
required
GitHub repository in
owner/repo format.string
required
Git tag to deploy. The tag must have a published GitHub release.
object
Saved per-instance environment variables as key-value pairs. These are
separate from measured
env values in tinfoil-config.yml.string[]
Names of existing Tinfoil-managed organization or repository secrets to inject.
For non-debug private-keyserver delivery, omit this field or send
[];
private names come from the measured config, not this selection.string[]
Names of existing org SSH keys to inject.
boolean
Enable debug mode.
string
Verified custom domain for the container.
string
Target host name. Explicit selection requires host-selection access, and the
host and requested GPU shape must be available to the organization.
string
Existing container UUID to replace. The old instance is stopped and removed
before the replacement is queued. A later replacement failure does not
restore the old instance.
boolean
Whether to mark an initial or changed selected tag as the repository’s latest
GitHub release once the container is running and serving production. Applies
only to a non-debug instance with a connected GitHub App and an active
repository. Defaults to
true.Example Request
Response
Without declared volume mounts, returns the created instance with statusdeploying; it transitions to running once deployment completes. With declared mounts, returns stopped and volume_slots, the named mounts from the config. Attach the selected disks, then call Deploy. A disk is required only for a mount with key_secret; optional mounts may remain empty. See persistent volumes.
Every container object carries update_strategy, either blue_green or replace, for its saved configuration. Update requests also check the target release, which may require a different strategy.
The connections object contains production and review, each either null when unavailable or an object with url, repo, and tag. Review describes the current blue/green candidate, including its review port and target tag, not the production connection. Use these values with a verified client; merely opening the URL is not attestation verification. A connection descriptor does not make a debug enclave confidential.
Plan an update
POST /api/containers/:id/update/plan accepts the same body as Update Container and returns a read-only current-to-target plan without deploying. It requires containers.update and the same organization, repository, and instance-name authorization as execution.
The plan includes read_only, instance_id, name, current and target resource objects (tag, cpus, memory_mb, gpus), update_strategy, downtime_required, hold, hold_source (project or request), hold_available, mark_latest_release, and volume_data (retained). configuration_changes reports added, changed, and removed names for variables, secrets, and ssh_keys, changed settings, and secrets_refreshed; values are not exposed. cost_estimate.available indicates whether an estimate is available, with reason when it is not.
A plan can report an unavailable hold or required downtime without requiring consent to inspect it. Execution still requires a valid hold choice and downtime consent, and revalidates the request. The plan is not a reservation or a historical snapshot.
Secret delivery in update plans
When the target config has a nonemptykeyserver-url, an instance plan includes
the optional secret_delivery object. In a project plan it is nested at
results[].plan.secret_delivery, not at the project response’s top level.
The object is omitted for configs without keyserver-url; absence is not
evidence that external secrets have been verified.
For a non-debug private target, the object has this shape:
Both name lists are arrays, never
null. The object contains no endpoint URL,
secret values, or bootstrap credentials. Registry authentication, certificate
authorization, and debug SSH are separate from these workload-secret lists.
Request secrets always means a managed selection. On deploy/update, omitted or
null selections retain saved bindings; send "secrets": [] explicitly when
switching to private delivery.
Nonempty managed selections and private names supplied in saved/request
variables are rejected. There is no implicit fallback to managed values.
In config-validation responses, YAML keyserver-url appears at
config.keyserver_url, model key-secret at config.models[].key_secret,
volume key-secret at config.volumes[].key_secret, and dummy attestation at
config.shim.dummy_attestation. Invalid keyserver URL syntax returns a validation
error with field: "keyserver_url" and code: "invalid_keyserver_url".
See private-secret requirements.
Update Container
endpoint
Replaces the version a
running container serves with a new tag, updated configuration, or both. The server evaluates the target release and volume configuration to choose the strategy. For a blue/green update (single GPU or CPU-only, no persistent volumes), the new version boots alongside the current one and traffic switches once it is ready. For a replacement update (multi-GPU or persistent volumes), the running instance stops first and the new version deploys in its place; the request must carry confirm_downtime: true and cannot be held for review. Containers in any other status return 409 with code INVALID_CONTAINER_STATE; use Deploy for stopped or failed containers.Path Parameters
string
required
The container UUID.
Request Body
All fields are optional. Omitted fields keep their current values, exceptmark_latest_release, which defaults to true for each operation, and hold,
which inherits the project’s current hold_by_default setting.
string
New git tag to deploy.
object
New saved per-instance environment variables. This replaces the full saved
map, but not measured
env values in tinfoil-config.yml.string[]
New saved Tinfoil-managed secret selection. Omitted or
null retains the
saved selection. In managed delivery, a supplied list replaces it, then merges
with declared secrets that exist in repository or organization scope.
Non-debug private delivery requires an empty managed selection: send []
explicitly to clear existing bindings; declared private values stay in your keyserver.string[]
New SSH key-name list. This replaces the full existing SSH key set.
boolean
Toggle debug mode.
string
Set or clear a custom domain. Pass an empty string to revert to the auto-generated domain.
boolean
Hold the new version for review and promotion while the current instance keeps
serving production. Available only for a blue/green update; requesting a hold
when the target release requires replacement returns
400 with code HOLD_UNAVAILABLE.
Omit to inherit the project default; explicit true or false applies to this
operation only and does not modify project settings.boolean
Required to be
true when the target update requires replacement. Without it the
request returns 409 with code DOWNTIME_CONFIRMATION_REQUIRED and the update
is not started.boolean
For a changed tag, whether to mark the selected tag as the repository’s latest
GitHub release once the new version is running and serving production, or
after promotion for a held version. Applies only to a non-debug instance
with a connected GitHub App and an active repository. Defaults to
true.host_name.
A blue/green update of a single-GPU container needs a second free GPU on the container’s host for the new version. When none is free the request returns 409 with code HOST_GPU_BUSY and the running instance is untouched. CPU-only updates have no such requirement.
Example Request
Stop Container
endpoint
Stops a running container and removes its DNS records. The container record, saved configuration, and attached volumes are preserved so it can be deployed again later.
Deploy Container
endpoint
Boots a new enclave for a
stopped or failed container, optionally with updated settings. A stopping container queues the deploy behind the stop without changing its tag or host; wait until stopped to change either. Deploys go straight to production and cannot be held for review. A running container returns 409 with code INVALID_CONTAINER_STATE; use Update instead.Request Body
All fields are optional. Omitted fields keep their saved values, exceptmark_latest_release, which defaults to true for each operation.
string
Git tag to deploy.
object
Saved per-instance environment variables. This replaces the full saved map,
but not measured
env values in tinfoil-config.yml.string[]
New saved Tinfoil-managed secret selection. Omitted or
null retains the
saved selection. In managed delivery, a supplied list replaces it, then merges
with declared secrets that exist in repository or organization scope.
Non-debug private delivery requires an empty managed selection: send []
explicitly to clear existing bindings; declared private values stay in your keyserver.string[]
SSH key-name list. This replaces the full saved SSH key set.
boolean
Toggle debug mode.
string
Set or clear a custom domain. Pass an empty string to revert to the auto-generated domain.
string
Deploy the container on a different available host. Host access and GPU
entitlement are rechecked. Attached volumes must be on the target host.
boolean
For a changed tag, whether to mark the selected tag as the repository’s latest
GitHub release once the container instance is running and serving production.
Applies only to a non-debug instance with a connected GitHub App and an active
repository. Defaults to
true.Delete Container
endpoint
Permanently deletes an instance and its running enclave. The project remains while it has other instances. Outstanding billing is finalized before deletion.
204 No Content on success.
Get Update Status
endpoint
Returns the status of an in-progress update.
Response
pending (queued), deploying (submitted and booting),
started (the enclave is running and startup checks are in progress), ready
(healthy and ready for traffic, or held and waiting for promotion), and failed (deployment
or startup checks failed).
Promote Update
endpoint
Promotes a held version ready for promotion (
update_status: "ready"), switches production traffic to it, and returns the updated container.Cancel Update
endpoint
Cancels an in-progress or failed update and returns
204 No Content. Updates whose strategy is replace cannot be canceled once the running instance has been stopped.Toggle GitHub App Connection
endpoint
Sets whether the container is connected to a GitHub App installation for its repo owner.
Request Body
boolean
required
Whether GitHub App connectivity should be enabled.
Get Container Metrics
endpoint
Returns CPU, GPU, and memory utilization time series for a container.
Query Parameters
string
default:"24h"
Time preset. Valid values:
5m, 15m, 30m, 1h, 24h, today, 7d, 30d, 60d, 90d, 180d, 365d, 3mo, 6mo, 12mo, all.data_points and interval. Utilization values are
average and maximum percentages for each bucket; memory totals report the
corresponding CPU or GPU capacity.
Projects
A project contains all container instances in an organization that use the same GitHub repository. It is created implicitly by the first instance or project-secret namespace; there is no explicit project-create endpoint. New projects havehold_by_default=false, inherited by individual and batch updates when hold is omitted.
List Projects
endpoint
Returns projects with aggregate instance counts and settings. A project groups the instances that share one config repository.
deploying_count combines instances in pending, deploying, started, and
stopping states.
There is no separate GET /api/containers/projects/:id endpoint. Resolve a project by ID or repository from the list response.
Update Project Settings
endpoint
Updates shared settings and returns the project.
boolean
Whether updates of this project hold new versions for review by default.
Update Project Instances
To inspect the same selection before updating,POST /api/containers/projects/:id/update/plan accepts the request body below and uses containers.projects.update authorization. It returns read_only, project_id, latest_release_tag, eligible/skipped/failed counts, and per-instance results with instance_id, name, status (planned, skipped, or failed), plan, and error. A planned result contains the same instance plan; skipped and failed results explain why no plan is available.
endpoint
Updates every running instance, or a selected set, to one repository tag.
string
required
Repository release tag to deploy.
boolean
Holding for review override for this request. Omit it to use
hold_by_default; an
explicit value overrides the saved default for this update only.boolean
For selected instances changing tags, whether to mark the selected tag as the
repository’s latest GitHub release once an instance is running and serving
production, or after promotion for held versions. Applies only to
non-debug instances with a connected GitHub App and an active repository.
Defaults to
true.string[]
Container UUIDs to update. Omit it to update every instance.
boolean
Required to be
true when any eligible targeted instance requires replacement
for the target release. Without it the whole request returns 409 with
code DOWNTIME_CONFIRMATION_REQUIRED and lists the affected instances; no
instance is updated.hold is requested, the whole request returns 400 with code HOLD_UNAVAILABLE and lists the affected instances; no instance is updated.
After preflight, the response contains one result per targeted instance with status updating, skipped, or failed. Only running instances are updated; stopped and failed instances are skipped (bring them up with Deploy), as are instances with an update already in progress.
Example Request
Model Weights
These endpoints back thetinfoil model CLI commands. They wrap Hugging Face model weights into verified artifacts that GPU containers load with integrity checking. See Model weights for the workflow. Access requires a GPU entitlement or model view access for the organization.
Wrap Model
endpoint
Starts a wrap job on a host and returns
202 Accepted with the job. If a job for the same repository, commit, and schema is already pending or running on that host, the existing job is returned instead of starting a new one.Request Body
string
required
Hugging Face repository, for example
google/gemma-4-31B-it.string
required
Target host name. The host must be available to the organization.
string
Repository commit to wrap. Defaults to the head of the default branch.
string
Hugging Face access token for gated or private repositories.
integer
Pack schema version. Omit or pass
0 for the default.Response
schema, image_digest, root_hash, offset, verity_uuid, and ended_at. Failed jobs include error.
List Wrap Jobs
endpoint
Returns wrap jobs across the organization, newest first.
integer
default:"20"
Maximum number of jobs to return, between 1 and 200.
Get Wrap Status
endpoint
Returns the current status of one wrap job, fetched live from the host. Includes
logs when available.Delete Wrap Job
endpoint
Deletes a wrap job and its artifact once no container references it. Returns
204 No Content, or 409 Conflict if the artifact is still in use.GitHub Repository Operations
These endpoints back thetinfoil repo CLI commands. They read and update a repository’s tinfoil-config.yml, and trigger and monitor release builds. The repository must be accessible through the organization’s GitHub App installation. Name-restricted scoped admin keys are denied.
Get Repository Config
endpoint
Returns the
tinfoil-config.yml from the default branch, both parsed and raw.Response
Open Config Pull Request
endpoint
Writes an updated
tinfoil-config.yml to a new branch and opens a pull request against the default branch. The branch name, commit message, and PR title are generated server-side.Request Body
Provide exactly one ofconfig or raw.
object
Structured config fields to apply. Managed keys are updated in place and unmanaged keys in the existing file are preserved.
string
Complete YAML document to write verbatim. Must parse as a valid config.
string
Pull request description.
Response
Get Pull Request
endpoint
Returns the state of a pull request:
pr_number, state, merged, and pr_url.Get Build Info
endpoint
Returns release and tag information used to plan the next build.
Response
has_new_commits is false only when the default branch head is exactly the commit tagged by the latest release.
Get Build Status
endpoint
Returns the release workflow run for a version, or
run: null if no matching run exists yet. Returns 404 if the repository has no .github/workflows/tinfoil-release.yml.string
Semver tag to look up, for example
v1.2.1. If omitted, returns the most recent run.Response
Dispatch Build
endpoint
Triggers the repository’s
tinfoil-release.yml workflow for a version.string
required
Semver string such as
v1.2.1. A leading v is added if missing.Response
Related Resources
Secrets
Organization and repository secrets are encrypted values injected into containers at deploy time. Secret names must beUPPER_SNAKE_CASE or kebab-case.
endpoint
Returns all org-level secrets as metadata only. Secret values are never returned.
endpoint
Returns metadata for a single secret, including which containers use it.
endpoint
Creates a new organization-scoped secret.
Request Body
string
required
Secret name.
string
required
Secret value.
POST /api/repositories/:owner/:repo/secrets with the same request body to
create a repository-scoped secret. The corresponding repository GET, PUT,
and DELETE endpoints use
/api/repositories/:owner/:repo/secrets/:name.
endpoint
Updates the value of an existing org secret.
endpoint
Deletes an org secret. If the secret is currently used by any container, the API returns
409 Conflict and includes the blocking container names.SSH Keys
SSH key names must be kebab-case, for examplemy-deploy-key.
endpoint
Returns all org-level SSH keys.
endpoint
Adds a new org SSH key for debug-mode containers.
Request Body
string
required
SSH key name in kebab-case.
string
required
SSH public key, for example
ssh-ed25519 AAAA....endpoint
Deletes an org SSH key. If the key is currently used by any container, the API returns
409 Conflict and includes the blocking container names.Custom Domains
endpoint
Returns all custom domains for the organization, including verification details and which containers use each domain.
endpoint
Adds a custom domain for verification and returns the TXT and CNAME records required for setup.
Request Body
string
required
Domain name to register, for example
api.example.com.endpoint
Checks DNS records and updates the domain’s verification state.
endpoint
Deletes a custom domain. If the domain is currently used by any container, the API returns
409 Conflict and includes the blocking container names.Registry Credentials
Private registry credentials are supported forghcr, gcr, and dockerhub.
endpoint
Returns credential status for each supported registry, including whether credentials exist, whether they are expired, and when they were last updated.
endpoint
Creates or updates credentials for a supported registry.
Path Parameters
string
required
Registry identifier:
ghcr, gcr, or dockerhub.Request Body
Forghcr:
gcr:
dockerhub:
endpoint
Deletes credentials for a supported registry.
Error Responses
Example error response:
Container lifecycle codes. The
error message says what to do next; show it to the user as is.



