New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@fidacy/sdk

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fidacy/sdk

Thin, typed client for the public Fidacy API. Bundles @fidacy/verify so you can check every signed verdict yourself.

latest
Source
npmnpm
Version
0.2.1
Version published
Maintainers
1
Created
Source

@fidacy/sdk

A thin, typed client for the public Fidacy API. It ships @fidacy/verify alongside it, so the verdict you get back is one call away from being independently verified.

Fidacy returns a signed verdict for an agent payment. The point of the SDK is not to make you trust that verdict: it is to get it, and hand you the tool to check the signature yourself.

Install

npm i @fidacy/sdk

Assess, then verify

import { Fidacy } from '@fidacy/sdk';

const fidacy = new Fidacy({ apiKey: process.env.FIDACY_API_KEY! }); // fky_test_… or fky_live_…

const result = await fidacy.assess({
  mandate: {
    vct: 'mandate.payment.1',
    payee: { id: 'merchant_demo', name: 'Demo Store' },
    payment_amount: { amount: 4299, currency: 'EUR' },
    payment_instrument: { id: 'pi_demo', type: 'card' },
  },
});

console.log(result.decision); // 'approve' | 'review' | 'deny'
console.log(result.score);    // 0..100

// Don't trust the response object — verify the signed payload yourself.
const verified = await fidacy.verify(result.riskPayloadJws);
console.log('signature valid:', verified.valid);
console.log('decisions match:', verified.claims.decision === result.decision);

fidacy.verify is @fidacy/verify's verifyRiskPayload, bundled so you don't add a second dependency. The assess call itself does no verification: it returns the API's response as-is, and you decide whether to trust it by checking the signature against Fidacy's public JWKS.

Not just payments

The verdict is action-generic. kind (default 'ap2_payment') accepts every action the engine assesses: 'ap2_payment' | 'message_send' | 'voice_call' | 'claim_document' | 'custom' (the exported AssessKind type). An agent sending a customer message, for example:

const verdict = await fidacy.assess({
  kind: 'message_send',
  mandate: {
    kind: 'message_send',
    actor_agent: 'did:web:agents.example.com:support-1',
    principal: 'org:example',
    channel: 'email',                 // 'whatsapp' | 'email' | 'sms'
    recipient_ref: 'cust_8f31',      // pseudonymized ref — never a raw address
    content_hash: 'sha256-9b2f…',    // hash only — the message never leaves you
    requested_at: Math.floor(Date.now() / 1000), // epoch seconds
  },
});
// verdict.riskPayloadJws is the signed, independently verifiable record
// that this send was assessed before it happened.

Each kind validates against its public JSON schema on the engine side; the payment path (ap2_payment) is unchanged and remains the default.

What assess returns

interface AssessResult {
  decision: 'approve' | 'review' | 'deny';
  score: number;            // 0..100
  assessmentId: string;
  riskPayloadJws: string;   // the signed verdict — pass to fidacy.verify
  signingKeyId: string;
  signals: Record<string, unknown>;
  outcome: Record<string, unknown>;
  spend_guard?: Record<string, unknown>;
  a2a?: { recommended_task_state: string; task_metadata: Record<string, unknown> };
}

Webhooks

Webhook events are verified for you. constructEvent checks the signature before returning, and throws if it does not hold.

const event = await fidacy.webhooks.constructEvent(
  rawBody,
  req.headers['x-fidacy-signature'],
);
// event.type, event.data — only reached on a valid signature.

Billing

const status = await fidacy.billing.get();
const { url } = await fidacy.billing.checkout({ tier: 'growth' });

Errors

A non-2xx response throws FidacyError. The message is static and never includes your key or the request body.

import { FidacyError } from '@fidacy/sdk';

try {
  await fidacy.assess({ mandate });
} catch (err) {
  if (err instanceof FidacyError) {
    console.error(err.type, err.status, err.rejection_reasons);
  } else {
    throw err;
  }
}

Options

new Fidacy({
  apiKey,            // required, sent as a Bearer token
  baseUrl,           // default 'https://api.fidacy.com'
  timeoutMs,         // per-request, default 10000
  maxRetries,        // idempotent calls only, default 2
  fetch,             // inject a fetch implementation
});

Retries apply only when you pass an idempotencyKey to assess, so a retried call can never double-charge or duplicate.

Consequential actions

assess produces a signed risk verdict. actionMandates is the stricter path for an action that changes the world: it creates bounded authority, then issues a short-lived grant for one exact request. The executor keeps the business data and credential; Fidacy receives only the action, resource, and a SHA-256 hash of the local context.

import { Fidacy, hashActionContext } from '@fidacy/sdk';

const fidacy = new Fidacy({ apiKey: process.env.FIDACY_API_KEY! });

const mandate = await fidacy.actionMandates.create({
  subject: 'support-refund-agent',
  version: 'fidacy.action-mandate.v1',
  allow: {
    actions: ['stripe.refund.create'],
    resources: ['stripe:payment_intent:pi_123'],
    maxActions: 1,
    maxDelegationDepth: 0,
  },
  window: {
    notBefore: new Date().toISOString(),
    notAfter: new Date(Date.now() + 15 * 60_000).toISOString(),
  },
});

const localRefund = { paymentIntentId: 'pi_123', amount: 1234 };
const contextHash = await hashActionContext(localRefund);
const result = await fidacy.actionMandates.decide(mandate.id, {
  action: 'stripe.refund.create',
  resource: 'stripe:payment_intent:pi_123',
  contextHash,
});

if (!result.grant) throw new Error(`Refund refused: ${result.violated_rule}`);
// Give result.grant to a Fidacy-enforcing executor. It must verify the grant,
// redeem it once, then and only then call Stripe.

Both ALLOW and DENY return a signed receipt. Operators can list decisions through fidacy.actionDecisions.list() and export independently verifiable evidence with fidacy.actionDecisions.incidentPack(decisionId).

License

Apache-2.0. Part of fidacy-open.

FAQs

Package last updated on 30 Jul 2026

Related posts