---
title: "Get a language file"
method: POST
path: "/language-files/get"
tags: ["Language Files"]
---

# Get a language file

`POST /language-files/get`

## Request

- Base URL: `https://api.reportingninja.com/v1`
- URL: `https://api.reportingninja.com/v1/language-files/get`
- Auth: HTTP bearer

Returns one language file -- one of the account's own or one of the sixteen the platform ships -- with a signed link to its .txt.

THE LITERALS NEVER TRAVEL IN JSON. A language file is six thousand lines and 370 to 420 KB, which is over half a megabyte once base64 encoded: download_url is a link to GET /v1/language-files/download that carries the account and the file inside it, needs no Authorization header and expires 900 seconds after this call (download_url_expires_at says when). Ask again for a fresh one.

It is the way to get the .txt that /v1/language-files/create and /v1/language-files/update take: download a file, edit the values, send it back.

## Request body

- LanguageFilesGetRequest
  - `language_file_key` string, required: The file. From /v1/language-files/list; the sixteen of the platform are named language_file_en, language_file_es and so on, and they can be read and downloaded.

## Response `200`

The call succeeded. This endpoint reports its errors with a real HTTP status, so a 200 always carries status=ok.

- LanguageFilesGetResponse
  - `status` 'ok', required
  - `data` LanguageFilesGetData, required
    - `language_file` LanguageFileDetail, required: One language file with the signed link its .txt is downloaded from. The literals never travel in JSON.
      - `language_file_key` string, required: The language file.
      - `name` string, nullable, required
      - `language` string, nullable, required: The ISO 639-1 code of the literals. Null on the files of the account made before the language was asked for.
      - `is_system` boolean, required: Whether the file is one of the sixteen the platform ships.
      - `file_name` string, nullable: The name of the .txt the file was uploaded from. Null for the files of the platform.
      - `internal_notes` string, nullable: A note for the account's own staff.
      - `download_url` string, nullable, required: A signed link to GET /v1/language-files/download for THIS file. It needs no Authorization header, is good for one file and expires 900 seconds after this call. Null on a node that does not publish a base URL for the API.
      - `download_url_expires_at` string, date-time, nullable, required: When download_url stops working (ISO 8601).
  - `meta` Meta, required
    - `request_id` string, required: Id of this request, useful when reporting an incident.
    - `timestamp` string, date-time, required: When the answer was built, in UTC.

## Other responses

- `400`: The request was refused before anything was written. INVALID_REQUEST covers the framework refusals of every endpoint (the Content-Type is not application/json, the body could not be read, the body is not valid JSON). The report endpoints add their own: VALIDATION_FAILED with details.problems, UNKNOWN_PARAM with the path of the field the endpoint does not read, and the single-field refusals MISSING_REQUIRED_FIELD, INVALID_VALUE and APPEND_NOT_ALLOWED. The description of each operation lists the ones it emits. Everything else a body can get wrong arrives as an entry of details.problems rather than as the code of the envelope.
- `401`: Invalid or missing Bearer token.
- `404`: A key of the request does not name anything this account owns. NOT_FOUND covers reports, sections, widgets, schedules, portal views, brand templates, email templates and language files; TEMPLATE_NOT_FOUND covers a catalog slug, version or section position that stopped being published between the validation and the write. An entity of another account is reported the same way as one that does not exist.
- `413`: The request body is over 1 MB. The cap is applied before authentication, so this answer is refused without the key being read, and it carries the usual error envelope.
- `429`: A budget was spent. RATE_LIMITED is the per-key read budget (300/minute, 5000/day) or the per-account write budget (60/minute, 1000/day). EMAIL_QUOTA_REACHED is the separate budget of 50 calls per account per day that send email, and its Retry-After points at the next UTC midnight. The Retry-After header gives the seconds until the more restrictive window resets. The X-RateLimit-* headers report the read budget, except on the 429 of a write, where they report the write budget.
- `500`: Internal server error.

---

[API](https://skmtc.dev/reportingninja/apis/reporting-ninja-api.md) · [All operations](https://skmtc.dev/reportingninja/apis/reporting-ninja-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reportingninja/apis/reporting-ninja-api/revisions/13876c71be34?raw)
