---
title: "Link child keys to a parent key"
method: POST
path: "/projects/{project_id}/keys/{id}/key_links"
tags: ["Linked Keys"]
---

# Link child keys to a parent key

`POST /projects/{project_id}/keys/{id}/key_links`

Designates a translation key as a parent and links one or more child keys to it. Once linked, child keys receive a special reference marker as their translation content, signalling that their translations are derived from the parent. Use this when you want to group related keys — for example, a short label and its long-form variant — so translators see them in context together.

Pass an empty child_key_ids array to mark the key as a parent without linking any children yet. Both the parent key and every child key must belong to the main project; branch keys cannot participate in key links. A child key can have at most one parent at a time; attempting to link a child that already has a parent returns a 422 error with code CHILD_IS_ALREADY_LINKED. Parent and child key plurality must match — linking a plural child to a non-plural parent (or vice versa) also returns a 422.

## Path parameters

- `project_id` string, required
- `id` string, required

## Headers

- `X-PhraseApp-OTP` string

## Request body

- object
  - `child_key_ids` string[], required — Codes of the keys to link as children. Pass an empty array to mark the parent key without linking any children.

## Response `201`

Key link reference created.

- KeyLink
  - `created_at` string, date-time — The timestamp when the link was created.
  - `updated_at` string, date-time — The timestamp when the link was last updated.
  - `created_by` UserPreview
    - `id` string
    - `username` string
    - `name` string
    - `gravatar_uid` string
  - `updated_by` UserPreview
    - `id` string
    - `username` string
    - `name` string
    - `gravatar_uid` string
  - `account` Account
    - `id` string
    - `name` string
    - `slug` string
    - `company` string
    - `created_at` string, date-time
    - `updated_at` string, date-time
    - `company_logo_url` string
  - `parent` KeyPreview
    - `id` string
    - `name` string
    - `plural` boolean
    - `use_ordinal_rules` boolean
  - `children` KeyPreview[] — The child translation keys linked to the parent.
    - `id` string
    - `name` string
    - `plural` boolean
    - `use_ordinal_rules` boolean

## Other responses

- `400` — Bad request. The request could not be parsed or a parameter failed validation. Verify the request body, the content type, and the parameter types, then retry.
- `401` — Unauthorized. Authentication failed because the access token is missing, expired, or invalid. Supply a valid access token and retry.
- `403` — Forbidden. The credentials are valid but not permitted for this request: the access token may lack the required scope, the user may lack permission on the resource, or the account plan may not include the feature. Use a token with the required scope on an account and user that hold the necessary permissions.
- `404` — Not found. The requested resource does not exist or is not visible to the authenticated user. Verify the identifiers in the request path and that the token has access to them, then retry.
- `422` — Unprocessable entity. The request was well-formed but failed validation. The response body lists each offending field in the `errors` array, with its resource, field, and a human-readable message. Correct the listed fields and retry.
- `429` — Too many requests. The rate limit has been exceeded. Wait until the time indicated by the `X-Rate-Limit-Reset` response header before retrying.

---

[API](https://skmtc.net/phrase/apis/control-hub-service.md) · [All operations](https://skmtc.net/phrase/apis/control-hub-service/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/phrase/control-hub-service/revisions/98ecac7ba2bf/schema)
