Protocol · Eligibility presentation

Abraxas Eligibility Presentation Protocol

A presentation is one audience-bound, one-time eligibility result. It is not a transferable identity passport, not a reusable bearer credential, and not automatic KYC or KYB approval. The partner backend must re-fetch the current public receipt and apply its own policy.

What this is

Any protocol can request one narrow KYC, KYB, authorized-signer, jurisdiction, age, membership, or policy result from Abraxas without collecting the holder’s underlying evidence or inventing its own verification stack. The envelope media type is application/abraxas-eligibility-presentation+json. This is a server-to-server presentation standard. Partners never send a receipt_id. Abraxas derives the one completed Hosted Partner Flow receipt bound to the presentation request. It is not a transferable identity passport, generic KYC form, raw credential wallet, browser-authoritative flow, or reusable bearer token.

Verification sequence

  1. Create the presentation request from your backend for one audience, policy, version, action, environment, and nonce.
  2. Redirect the holder to Hosted Partner Flow. Fresh consent is required.
  3. Issue with only request_ref and the original verifier nonce. Abraxas derives the completed receipt. Partners never send a receipt_id.
  4. Verify signature and key lifecycle, then re-fetch GET /api/receipts/{id}/public before any grant.
  5. A presentation is never a bearer credential or automatic KYC/KYB approval.

Discover envelope versions and endpoints at /.well-known/abraxas-eligibility. Signatures reuse the existing Ed25519 receipt verification-key lifecycle. There is no parallel signing trust.

KYC/KYB planning posture

These planning categories are Utila-compatible private result shapes only. There is no live Utila API, wallet governance, AML/KYT, quorum, or transaction-policy integration. A protocol such as Utila still runs those controls after an Abraxas result.

organization_eligible, authorized_signer, jurisdiction_eligible, and institutional_counterparty_eligible are planning categories only. They flow through Policy Proposals → Release Candidates → a reviewed catalog change. A browser or partner cannot self-publish them as a live policy.

Server example

import { AbraxasPartnerKit } from "@abraxas/partner-kit";

const kit = new AbraxasPartnerKit({
  partnerId: process.env.ABRAXAS_PARTNER_ID,
  policyId: process.env.ABRAXAS_POLICY_ID,
  policyVersion: Number(process.env.ABRAXAS_POLICY_VERSION),
  requirePolicyVersion: true,
  environment: "sandbox",
  baseUrl: process.env.ABRAXAS_BASE_URL,
});

export async function requestEligibilityPresentation(nonce) {
  const created = await fetch(process.env.ABRAXAS_BASE_URL + "/api/v1/eligibility-presentations/requests", {
    method: "POST",
    headers: {
      "content-type": "application/json",
      authorization: "Bearer " + process.env.ABRAXAS_SANDBOX_API_KEY,
    },
    body: JSON.stringify({
      policy_id: process.env.ABRAXAS_POLICY_ID,
      policy_version: Number(process.env.ABRAXAS_POLICY_VERSION),
      purpose: "Confirm one protocol eligibility result",
      action: "retail_access",
      action_scope: "sandbox:protocol_access",
      environment: "sandbox",
      result_category: "age_21",
      verifier_nonce: nonce,
    }),
  }).then((res) => res.json());
  return created.hosted_verify_url;
}

export async function issueEligibilityPresentation(requestRef, nonce) {
  const issued = await fetch(process.env.ABRAXAS_BASE_URL + "/api/v1/eligibility-presentations/issue", {
    method: "POST",
    headers: {
      "content-type": "application/json",
      authorization: "Bearer " + process.env.ABRAXAS_SANDBOX_API_KEY,
    },
    body: JSON.stringify({
      request_ref: requestRef,
      verifier_nonce: nonce,
    }),
  }).then((res) => res.json());
  return issued.envelope;
}

export async function verifyEligibilityPresentation(envelope, nonce) {
  const verified = await fetch(process.env.ABRAXAS_BASE_URL + "/api/v1/eligibility-presentations/verify", {
    method: "POST",
    headers: { "content-type": "application/abraxas-eligibility-presentation+json" },
    body: JSON.stringify({
      envelope,
      expected: {
        verifier_nonce: nonce,
        policy_id: process.env.ABRAXAS_POLICY_ID,
        policy_version: Number(process.env.ABRAXAS_POLICY_VERSION),
        action: "retail_access",
        environment: "sandbox",
      },
    }),
  }).then((res) => res.json());
  if (!verified.ok) return { action: "deny", presentation_sufficient: false };
  const receipt = await kit.fetchPublicReceipt(verified.payload.receipt_verification_ref);
  if (!receipt.ok) return { action: "deny", presentation_sufficient: false };
  const evaluated = kit.evaluateFetchedReceipt(receipt.receipt);
  return { ...evaluated, presentation_sufficient: false };
}
Continue from hereIntegration StudioStarter KitLaunchpadPartner Flow docs