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

# TypeScript ACI Verifier

> Use the official TypeScript SDK to verify Phala Private AI attestation, pin the TLS channel, and audit signed response receipts.

`@phala/aci-verifier` is the official TypeScript implementation of the ACI
client checks. Node.js and Bun applications can use it to establish an
instance-scoped, SPKI-pinned connection before sending model traffic. The
package is ESM-only and supports Node.js 20.18.1 or newer and Bun 1.4.0 or
newer.

## Install

```bash theme={"system"}
npm install @phala/aci-verifier openai
```

## Create a verified connection

```typescript theme={"system"}
import OpenAI from "openai";
import { connectAci } from "@phala/aci-verifier/runtime";

const apiKey = process.env.PHALA_AI_API_KEY;
if (!apiKey) throw new Error("PHALA_AI_API_KEY is required");

const aci = await connectAci({
  baseURL: "https://inference.phala.com/v1",
  serving: {
    requireVerified: true,
    requireReceipt: true,
  },
});

try {
  const client = new OpenAI({
    baseURL: aci.baseURL,
    apiKey,
    fetch: aci.fetch,
  });

  const response = await client.chat.completions.create({
    model: "z-ai/glm-5.3",
    messages: [{ role: "user", content: "Explain attestation." }],
  });

  const audit = await aci.verifyReceipt();
  if (!audit.transcript.verdict.verified) {
    throw new Error(audit.transcript.verdict.line);
  }

  console.log(response.choices[0].message.content);
} finally {
  await aci.close();
}
```

`connectAci()` verifies a fresh nonce-bound workload report and creates a
hostname-validated TLS transport pinned to the attested SPKI. Its scoped
`fetch` rejects non-HTTPS and cross-origin requests, expired workload
identities, TLS key mismatches, and missing receipt ids, and requires verified
serving in JSON inference requests.

## Receipt auditing

The runtime records the exact request and response wire digests while the body
is consumed. Call `verifyReceipt()` after the response finishes to fetch and
verify the latest signed receipt, including its signature, request and response `body_hash` values,
verified upstream status, and cited session. Pass a receipt id returned by
`aci.receipts()` to audit another retained exchange.

The default local history is the latest 32 receipt-bearing requests and exists
only for the current process. Gateway receipts and sessions follow the
deployment's server-side retention policy.

> [!WARNING]
>
> The low-level SDK does not automatically call `verifyReceipt()` for every
> response. Applications must make that call before accepting a result.
> Private AI Proxy audits every receipt automatically after delivery.

## Browser use

The browser export can verify attestation and receipt documents, but browser
JavaScript cannot observe the server certificate SPKI. It therefore cannot
enforce the same pinned transport by itself. Use the Node.js or Bun runtime
export when the application must bind model traffic to the attested TLS key.

## Release policy

The SDK does not check whether the gateway runs a production or development
dstack OS image. For OS-image assurance, verify the same quote, event log, and
VM configuration with an independent [dstack verifier](https://github.com/Dstack-TEE/dstack/tree/next/dstack/verifier)
and require `is_valid: true`.

Attestation proves which compose hash was measured, but not that your
organization reviewed that release. When you have an authenticated allowlist,
pass its hashes as `policy.acceptedComposeHashes`. Never copy a hash from the
endpoint and trust it on first use.

Each production release of the gateway at `inference.phala.com` is published as a
`gateway-prod-<date>` release in
[`Dstack-TEE/private-ai-gateway`](https://github.com/Dstack-TEE/private-ai-gateway/releases).
It lists the compose hash, OS and KMS values, and TLS keys, and attaches the exact
measured `app_compose.json` so you can recompute the compose hash yourself. A change
to these values is published as a prerelease at least 3 days before the rollout,
or sooner for an urgent change, with the reason in the release.
KMS values are the exception: `mr-kms` is recorded when a replica boots and can
change without notice, so pin the KMS root key instead. The
[release measurements page](https://docs.redpill.ai/guides/release-measurements)
lists the current values and the full notice policy.

Without a compose allowlist, the client verifies that the measured compose ran
in a genuine TDX workload. It does not claim that Phala reviewed that release.
For a production security decision, pair compose appraisal with a dstack
verifier result for the same quote, event log, and VM configuration, and require
`is_valid: true`.

For the complete API and security limits, see the
[`@phala/aci-verifier` package documentation](https://github.com/Dstack-TEE/private-ai-gateway/tree/main/clients/verifier-ts).

> [card] [Verify Attestation](https://docs.phala.com/phala-cloud/confidential-ai/verify/verify-attestation.md)

> [card] [Verify a Response](https://docs.phala.com/phala-cloud/confidential-ai/verify/verify-signature.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.