> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracklysms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Child Account

> Provision a new child account under your parent, optionally keyed to your own identifiers and pooled to the parent's billing.

Creates a child account under your parent. Use your **parent** key. Requires the `accounts.write` scope (or an unscoped grandfathered key). See [Accounts & Hierarchy](/api-reference/v2/accounts/overview) for the model.

<Note>
  This endpoint is [idempotent](/api-reference/v2/idempotency): send an `Idempotency-Key` header to make retries safe. Duplicate businesses are separately prevented by `externalIds.locationId` uniqueness.
</Note>

## Body Parameters

<ParamField body="name" type="string" required>
  Display name for the child account. Max 255 characters.
</ParamField>

<ParamField body="externalIds" type="object">
  Your own identifiers for this account. Each value is a non-empty printable-ASCII string, max 128 characters, and **immutable once set**. Unknown keys are rejected.

  <Expandable title="externalIds">
    <ParamField body="partnerId" type="string">Your partner/tenant identifier.</ParamField>
    <ParamField body="businessId" type="string">Your business identifier.</ParamField>
    <ParamField body="locationId" type="string">Your location identifier. **Globally unique within a parent** — a duplicate returns `409 duplicate_location`.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="paidIntent" type="boolean" default="false">
  Whether this child should be a paid account. When `false`, the child is created on the free plan and self-pays, and `billedByParent` is ignored.
</ParamField>

<ParamField body="billedByParent" type="boolean" default="true">
  Whether the parent pools this child's billing. **Only honored when `paidIntent` is `true`.** When honored, the child is created on the paid plan and the parent must have a payment method on file.
</ParamField>

## Response Fields

<ResponseField name="child" type="object">
  The created child.

  <Expandable title="child">
    <ResponseField name="accountId" type="integer">The new account's ID — use it in the child-scoped account endpoints.</ResponseField>
    <ResponseField name="name" type="string">Display name.</ResponseField>
    <ResponseField name="status" type="string">`active`.</ResponseField>
    <ResponseField name="plan" type="string">`paid` or `free`, per the billing fields above.</ResponseField>
    <ResponseField name="externalIds" type="object">The external IDs you supplied.</ResponseField>
    <ResponseField name="billedByParent" type="boolean">Whether billing pools to the parent.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO-8601 creation time.</ResponseField>
    <ResponseField name="payerDowngraded" type="boolean">Present only if the requested paid/pooled state was downgraded (e.g. parent had no payment method path); indicates the child was created self-paying instead.</ResponseField>
  </Expandable>
</ResponseField>

## Examples

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.tracklysms.com/api/v2/accounts/children \
    -H "X-Api-Key: trk_your_parent_key" \
    -H "Idempotency-Key: create-child-loc-west-0001" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Acme West",
      "externalIds": { "partnerId": "p_1", "businessId": "b_9", "locationId": "loc_west" },
      "paidIntent": true,
      "billedByParent": true
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.tracklysms.com/api/v2/accounts/children",
      headers={
          "X-Api-Key": "trk_your_parent_key",
          "Idempotency-Key": "create-child-loc-west-0001",
      },
      json={
          "name": "Acme West",
          "externalIds": {"partnerId": "p_1", "businessId": "b_9", "locationId": "loc_west"},
          "paidIntent": True,
          "billedByParent": True,
      },
  )
  child = resp.json()["child"]
  print(child["accountId"])
  ```
</RequestExample>

<ResponseExample>
  ```json Success (201) theme={null}
  {
    "child": {
      "accountId": 1042,
      "name": "Acme West",
      "status": "active",
      "plan": "paid",
      "externalIds": { "partnerId": "p_1", "businessId": "b_9", "locationId": "loc_west" },
      "billedByParent": true,
      "createdAt": "2026-07-26T14:03:11.123456"
    }
  }
  ```

  ```json Duplicate location (409) theme={null}
  {
    "error": "A child with this locationId already exists",
    "code": "duplicate_location",
    "existingAccountId": 1042
  }
  ```
</ResponseExample>

## Error Codes

| HTTP Status | Error Code                       | Description                                                                   |
| ----------- | -------------------------------- | ----------------------------------------------------------------------------- |
| 400         | `missing_name`                   | `name` is required.                                                           |
| 400         | `name_too_long`                  | `name` exceeds 255 characters.                                                |
| 400         | `invalid_external_ids`           | An external ID is malformed, too long, empty, or an unknown key was supplied. |
| 400         | `invalid_paid_intent`            | `paidIntent` is not a boolean.                                                |
| 400         | `invalid_billed_by_parent`       | `billedByParent` is not a boolean.                                            |
| 400         | `children_cap_exceeded`          | The parent has reached its 100-children limit.                                |
| 400         | `invalid_body`                   | The request body is not a JSON object.                                        |
| 403         | `not_a_parent_account`           | The calling key belongs to a child account.                                   |
| 403         | `sandbox_read_only`              | Sandbox keys cannot create children.                                          |
| 403         | `insufficient_scope`             | The key lacks the `accounts.write` scope.                                     |
| 409         | `duplicate_location`             | `externalIds.locationId` is already in use (see `existingAccountId`).         |
| 409         | `parent_payment_method_required` | A pooled paid child needs a parent payment method on file.                    |
| 429         | `rate_limited`                   | Child-creation rate limit (100/hour) hit; see the `Retry-After` header.       |

Authenticated requests can also fail with `401 invalid_credentials`, `403 account_suspended`, and rare `502 link_failed` / `503 rate_limiter_unavailable` transients.

## Next Steps

<CardGroup cols={2}>
  <Card title="Mint an API key" icon="key" href="/api-reference/v2/accounts/create-api-key">
    Issue a scoped key for the new child.
  </Card>

  <Card title="Register a webhook" icon="webhook" href="/api-reference/v2/webhooks/create-endpoint">
    Receive signed events for this child.
  </Card>
</CardGroup>
