# Admin: Join Cluster
## Endpoint
`/api/admin/cluster/primary/join`
## Method
GET
## Description
Used by a DNS Server instance to ask the Primary node to allow it to join the Cluster as a Secondary node. This call can only be made at the Primary node.
Note: This is the Primary-side API that registers a Secondary node. It is typically called by the Secondary node itself during the Initialize and Join Cluster flow, not directly by end users.
## Authentication
Required. Token must be provided via the `token` parameter.
## Permissions
Administration: Delete
## Parameters
| `token` | string | Yes | No | The session token generated by the `login` or the `createToken` call. |
| `secondaryNodeId` | integer | Yes | No | The Secondary node ID that was generated randomly when the server is initializing as a Secondary node. |
| `secondaryNodeUrl` | string | Yes | No | The HTTPS URL of the Secondary node's API web service. |
| `secondaryNodeIpAddresses` | string | Yes | No | A comma-separated list of Secondary node IP addresses. |
| `secondaryNodeCertificate` | string | Yes | No | The Secondary node's TLS certificate used by the API web service. |
## Response Fields
| `clusterInitialized` | boolean | `true` indicating the cluster is active. |
| `dnsServerDomain` | string | The FQDN of this DNS server. |
| `version` | string | The DNS server software version. |
| `clusterDomain` | string | The cluster domain name. |
| `heartbeatRefreshIntervalSeconds` | integer | Heartbeat refresh interval. |
| `heartbeatRetryIntervalSeconds` | integer | Heartbeat retry interval. |
| `configRefreshIntervalSeconds` | integer | Config refresh interval. |
| `configRetryIntervalSeconds` | integer | Config retry interval. |
| `configLastSynced` | string (datetime) | Timestamp of last config sync. |
| `nodes` | array | List of all cluster node objects including the newly joined Secondary. |
| `nodes[].id` | integer | Unique node ID. |
| `nodes[].name` | string | Node FQDN. |
| `nodes[].url` | string | Node HTTPS API URL. |
| `nodes[].ipAddresses` | array of strings | Node IP addresses. |
| `nodes[].type` | string | Node type: `Primary` or `Secondary`. |
| `nodes[].state` | string | Node state: `Self`, `Connected`, or `Unreachable`. |
| `nodes[].lastSeen` | string (datetime) | Timestamp of last contact. |
## Conditional Logic Notes
- This call can only be made at the Primary node.
- The `secondaryNodeCertificate` is used by the Primary to authenticate TLS connections to the Secondary node.
- All four Secondary node parameters are required.
## Edge Cases
- This endpoint is typically invoked programmatically by the Secondary node during the join process, not by end users directly.
- A newly joined Secondary node may appear with `state: "Unreachable"` until the first heartbeat completes.
- If a Secondary node with the same ID already exists, the behavior is undefined (likely an error or an update).