Node SDK
@graypass/node requests canonical decisions, manages supported subject and action operations, verifies proofs, and supplies Express and webhook helpers. It runs on your backend with a secret credential. The documented version is 1.0.0. Download the Node SDK archive, verify it with the installation instructions, and install the prebuilt package:
npm install --ignore-scripts ./graypass-node-1.0.0.tgz
The runnable example targets Node.js 22.17 or later in the Node 22 line.
Client configuration
import { GrayPassClient } from '@graypass/node';
const graypass = new GrayPassClient({
apiKey: process.env.GRAYPASS_SECRET_KEY!,
endpoint: 'https://app.graypass.org',
keysUrl: 'https://app.graypass.org',
issuer: 'https://app.graypass.org',
timeoutMs: 5000,
});
Set the required apiKey to your secret server or admin credential. The default API endpoint is https://api.graypass.org; the hosted app origin also serves the canonical API. keysUrl is the configured trusted base origin used to retrieve published proof keys. issuer defaults to the hosted issuer shown above.
You may independently configure tenantId, environmentId, and a replayStore. When either identity binding is absent, verification obtains it through credential(). That response is cached for the client lifetime. Public key retrieval is cached separately, with a refresh on an unknown key ID. Keep endpoint, key origin, and issuer consistent with the service configuration supplied for your environment.
Supported methods
| Method | Purpose |
|---|---|
credential() |
Inspect tenant, environment, scope, key mode, and reported proof issuer |
createSubject(input) |
Create or retrieve a scoped subject from a stable external reference |
createClientToken(subject, { origin, ttlSeconds }) |
Mint a short-lived browser token for a registered origin |
completeEnrollment(subject, session) |
Complete enrollment after the server reports readiness |
createPasskeyRegistrationGrant(subject) |
Issue a one-time grant after your authenticated account checks |
revokePasskey(subject, passkeyId) |
Remove a registered subject passkey |
revokeSubject(subject) |
Revoke the subject's existing operational reliance |
deleteSubject(subject) |
Delete supported subject operational records |
exportSubject(subject) |
Return the bounded export described in the subject guide |
registerAction(input) |
Register an action using admin scope; starts in shadow mode |
updateAction(id, input) |
Update display fields or request a mode change; handle a refused transition without changing the execution path |
authorize(input) |
Request a decision and verify the returned request hash against local input |
getAuthorization(id) |
Retrieve an authorization trace and nested proof information |
reportOutcome(id, outcome, note?) |
Record one immutable customer-reported outcome |
jwks() |
Obtain the published proof key set |
verify(proof, expectations) |
Check signature and expected claims locally using available or fetched keys |
verifyOnline(proof, expectations) |
Check server state and optionally consume; consumption defaults to true |
actionHash(input) |
Recompute the canonical action binding |
Use direct HTTP for operations without a convenience method, including policy activation, assessment retrieval, review, recovery, and evaluation management. See API reference.
Configure modes using Actions and policies. If the service refuses a mode transition, the action retains its previous mode. After an ambiguous timeout, retrieve the action's current state before retrying.
Authorization inputs and results
authorize() accepts subject, action, resource, audience, optional context, session, human actor, nonce, idempotencyKey, and requestedAt. The backend supplies authenticated identity and validated resource ownership. Context must obey the registered schema and canonical integer-safe request rules.
Supply a stable idempotency key for one logical request. If you supply that key but omit a nonce, the SDK derives a stable nonce for retries. Without a key, it generates a new request identity. Persist the original business material, nonce, and idempotency key. A transport retry may refresh requestedAt within the API freshness window while retaining that saved binding; it remains the same logical operation. See request conventions.
The result contains decision, mode, assurance, reason codes, challenge, compact proof when applicable, trace information, and verification.nonce and verification.actionHash. The latter is computed locally from the submitted request. getAuthorization() returns a different trace shape: access its compact proof as trace.proof?.compact.
Express integration
protect() and clientTokenRoute() are exported by the package and the Express entry point. clientTokenRoute() must be mounted behind your application's authentication and use a server-resolved subject and registered origin. Your application authenticates the customer before calling the handler.
protect() takes the client, action key, audience, and callbacks for subject, resource, optional context, and optional idempotency key. For an enforce-mode allow, it verifies the locally bound proof and consumes it online before calling the next handler. Test and shadow modes return a non-executing response. Challenge, hold, denial, missing proof, failed verification, and unavailable dependencies do not call the protected handler.
Default responses are challenge 401, hold 202, deny 403, and unavailability 503. onUnavailable: 'hold' returns 202 while preserving non-execution. Use custom response callbacks to present the result; execute the protected mutation only through the verified handler. For asynchronous resumption, connect the middleware to your durable pending-request and challenge-resume ledger using the integration guide.
Verification and webhooks
@graypass/node/verify exports verifyProof, fetchJwks, actionHash, and MemoryReplayStore, plus the relevant types. Supply explicit expected issuer, tenant, environment, audience, action, and action hash when calling the standalone verifier. Use a shared replay strategy across a fleet and complete online consumption before execution.
parseWebhook(rawBody, signatureHeader, secret, v2Headers) verifies the exact raw bytes and parses the event. Require the V2 signature, timestamp, and delivery ID before calling it. See the complete webhook handler, including canonical event deduplication and rotation.
Errors and retries
HTTP failures raise GrayPassApiError with status and code; malformed or non-JSON error responses are also surfaced as errors. The client applies its configured timeout. Your application owns retry and business transaction policy. Catch failures, preserve non-execution, and retry only according to the operation's idempotency semantics.
Report an executed outcome after your application confirms execution. Retry a failed outcome report through your own outbox rather than repeating the consequential operation.
For direct actionHash calls, explicitly supply actorType: 'human'. The direct helper requires this value at runtime. GrayPassClient.authorize() supplies it automatically for human actions.