---
title: "Get Runtime Bundle"
method: GET
path: "/v1/projects/{project_id}/translations/runtime"
tags: ["translations"]
---

# Get Runtime Bundle

`GET /v1/projects/{project_id}/translations/runtime`

## Request

- Base URL: `https://api.sonenta.dev`
- URL: `https://api.sonenta.dev/v1/projects/{project_id}/translations/runtime`
- Auth: none declared

Build a translation bundle ON DEMAND for the dev SDK.

Auth: ApiKey only (CurrentUser falls through to 401), viewer-equivalent
scope required (project:read / write / cdn:write / *) — a read of project
content, gated like the REST reads. For env_type='dev' keys, IP/origin
allowlist enforced. Response shape mirrors the CDN bundle (nested JSON tree)
so the SDK parses base and overlays identically.

`surface` (task 1716): the dev SDK reads BASE bundles from this authed
endpoint, not the CDN, and the endpoint had no overlay shape — so a11y
overlays never loaded in dev and the SDK short-circuited them to {}. This
serves the SAME sparse overlay build_payload emits for the CDN. Crucially an
EMPTY overlay is 200 {}, not a 404: empty != missing, which is why the dev
SDK can ask every boot without a false alarm.

## Path parameters

- `project_id` string, required

## Query parameters

- `language` string, required: BCP-47 language code
- `namespace` string, required: Namespace slug
- `version_slug` string, nullable: Project-version slug. Defaults to the production version.
- `surface` string, nullable: a11y surface overlay: aria_label | alt_text | screen_reader | plain_language. Omit for the BASE bundle. Returns a SPARSE overlay (only keys with an override for that surface); a surface with no overrides returns 200 with an empty body, NOT a 404.

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/sonenta/apis/sonenta-api.md) · [All operations](https://skmtc.dev/sonenta/apis/sonenta-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sonenta/apis/sonenta-api/revisions/f853ea49fb05?raw)
