# SDK reference

Reference for `@usewire/sdk` 0.3.x. The wire format mirrors the server's `/api/v1/sdk/*` responses; the OpenAPI spec is the canonical contract.

## Methods

| Method | Blocks? | What it does |
|--------|---------|--------------|
| `connect(options?)` | Yes | Full connect: prompt, wait for the user to pick a container, return a `Connection` |
| `beginConnect(options?)` | No | Start a connect handshake, return a persistable `PendingConnection` handle |
| `checkConnection(pending)` | No | Single poll of a pending handshake: `Connection` when ready, `null` while pending |
| `getStatus(apiKey)` | No | Live container and connection snapshot |
| `claim(apiKey, options?)` | Yes | Mint a claim link, prompt the user, resolve when the container is permanent |
| `getClaimUrl(apiKey)` | No | Mint a claim link and nothing else |
| `disconnect(apiKey)` | No | Revoke the connection; the install identity survives |

Blocking methods poll every 2 seconds with a 5-minute default timeout.

## Types

<Tabs syncKey="lang">
  <TabItem label="TypeScript">
    ```typescript
    interface Connection {
      mcpUrl: string;           // MCP endpoint, Bearer auth with apiKey
      apiUrl: string;           // REST base, same auth
      apiKey: string;           // container-scoped credential
      containerId: string;
      containerName: string;
      orgSlug: string | null;
      expiresAt: Date | null;   // non-null only for ephemeral containers
      agentId: string;
      credentialId: string;
      deviceKey: DeviceKey;     // persist to reuse the install identity
      connectedAt: Date;
      label?: string;
    }

    interface PendingConnection {
      userCode: string;         // show this to the user
      url: string;              // connect-screen URL
      nonce: string;
      deviceKey: DeviceKey;
      expiresAt: Date;          // handshake lapses after ~10 minutes
      label?: string;
    }

    interface ClaimLink {
      url: string;              // single-use, valid 30 minutes
      expiresAt: Date;
    }

    interface StatusSnapshot {
      container: {
        id: string;
        name: string;
        mcpEndpoint: string;
        organizationSlug: string;
        isEphemeral: boolean;
        createdAt: Date;
        ephemeralExpiresAt: Date | null;
      };
      connection: {
        id: string;
        connectedAt: Date;
        lastUsedAt: Date | null;
        label: string | null;
      };
      agent: { id: string; name: string; verified: boolean };
    }

    // claim() resolves with the snapshot plus a top-level expiry
    interface ClaimResult extends StatusSnapshot {
      expiresAt: Date | null;   // null once permanent
    }

    interface DeviceKey {
      credentialId: string;     // assigned on first connect
      publicKey: string;
      privateJwk: JsonWebKey;
    }
    ```
  </TabItem>
</Tabs>

`PendingConnection` and `DeviceKey` are plain data and survive a JSON round-trip, so they can be persisted anywhere.

## Errors

Rejected promises throw `WireSdkError` with a `code` and, when the server responded, an HTTP `status`.

| Code | Meaning |
|------|---------|
| `NOT_CONNECTED` | A method needing an apiKey was called without one |
| `NONCE_EXPIRED` | The connect handshake lapsed before the user finished |
| `POLL_TIMEOUT` | `connect()` gave up after its timeout; start a fresh connect |
| `CLAIM_TIMEOUT` | `claim()` gave up waiting; the link stays valid for 30 minutes |
| `ALREADY_CLAIMED` | The container is already permanent |
| `UNAUTHORIZED` | The apiKey is invalid or was revoked |

## Runtime support

Node 18+, Cloudflare Workers, Deno, Bun. The blocking `connect()` and `claim()` assume they can put a prompt in front of the user; in environments where they can't, use the non-blocking primitives and present the code or link through your own surface.

## Source

[github.com/usewire/wire-sdk](https://github.com/usewire/wire-sdk) · [@usewire/sdk on npm](https://www.npmjs.com/package/@usewire/sdk) · MIT licensed.