---
title: "SDK Pairing"
url: "https://control.actana.ai/docs/pairing/sdk-pairing"
description: "pairWithCore from @actana/sdk: redeem a code programmatically and hold the registration blob safely."
updated: 2026-09-01T09:03:07+00:00
---

A program pairs the same way an operator does: a short code from [`actana pair new`](/docs/pairing/create-a-pairing-code), a fingerprint compared before the code is sent, a CSR signed by the Core. `pairWithCore` from [`@actana/sdk`](/docs/reference/sdk) does the whole exchange.

```bash
npm install @actana/sdk
```

```js
import { pairWithCore } from "@actana/sdk/core-pairing";

const blob = await pairWithCore({
  address: "core.example.com:8443",
  code: "XXXX-XXXX",
  sessionId,
  expectedCaFingerprint, // required — absent is not a skip
});
```

The client's private key is generated locally and never sent. The CA fingerprint is compared **before** the code is posted — `expectedCaFingerprint` is required, because [absent is not waived](/docs/pairing/how-pairing-works#the-ca-fingerprint). `POST /v1/pair/redeem` is the only pre-auth route on a Core.

## Showing the fingerprint first

A UI that wants the operator to confirm the fingerprint before anything is spent uses `fetchCorePairingIdentity`: it dials with no code and returns the CA the Core presented, so you can render the fingerprint without leaking a secret you were never given. That is exactly what the Panel's **Add a Core** form and the CLI's interactive prompt do.

## The registration blob

The resolved value is a **registration blob**: `clientKey`, PEMs, and the bearer. It is what a paired client *holds*, not what a human carries — treat it like a private key and **never log it**. Feed it to `CoreClient.fromRegistrationBlob(blob)` to open a [core link](/docs/architecture/core-link).

```js
import { CoreClient } from "@actana/sdk/core-client";

const client = CoreClient.fromRegistrationBlob(blob, { connectTimeoutMs: 15_000 });
await client.connect();
```

Refusals surface as typed failures matching the classes on [Actana CLI Pairing](/docs/pairing/cli-pairing) — unreachable, fingerprint mismatch, hostname mismatch, refused, rate limited — the CLI is a thin skin over this same module.

## See also

- [SDK](/docs/reference/sdk) — `CoreClient`, `CoreSession`, file routes.
- [How Pairing Works](/docs/pairing/how-pairing-works)
- [Create a Pairing Code](/docs/pairing/create-a-pairing-code)
- [Core Link](/docs/architecture/core-link)
