Developers · Portable action contract
Preflight one named partner action
Abraxas remains the private eligibility and authorization layer. It is not an exchange, broker, custodian, wallet, payment processor, order router, token issuer, or execution engine. Allowed means the partner may perform its own named action. Abraxas never executes the trade, payment, membership grant, wallet connection, or protocol call.
Architecture
holder -> Abraxas hosted /partner/verify
Abraxas -> signed eligibility receipt
partner server -> GET /api/receipts/{id}/public
partner server -> AbraxasPartnerKit.evaluateFetchedReceipt
partner server -> issue portable action contract
partner server -> preflight named action + narrow scope
lifecycle / webhook -> re-fetch public receipt; webhook body is never a grant
browser <- { allowed, reason, action_binding, expires_at }
partner system <- performs its own named action if allowedA webhook event is not authorization. Fetch GET /api/receipts/{id}/public and verify the signed receipt on your server before granting access.
What allowed means
An allowed result means the partner may perform its own named action. Abraxas never grants membership, submits a trade, charges a card, signs a transaction, or calls a protocol. Trading Venue Adapter still uses enable_market_access. Payment Authorization Adapter still uses authorize_checkout and authorize_recurring_payment. Solana remains a no-funds eligibility gate. Wallet Standard stays message-only.
Examples
- Membership / access: grant_membership_access in sandbox:membership_access.
- Trading market access: enable_market_access in sandbox:market_access.
- Payment authorization: authorize_checkout or authorize_recurring_payment.
- Generic partner protocol: partner_protocol_action in sandbox:partner_protocol.
- EVM partner eligibility: enable_protocol_access, enable_member_access, enable_redemption_access.
Privacy contract
- Google sign in creates an Abraxas account. It does not prove age, identity, residency, or eligibility.
- A webhook event is not authorization. Fetch GET /api/receipts/{id}/public and verify the signed receipt on your server before granting access.
- The Solana Partner Adapter never creates a transaction, mints a token, or moves funds. It binds an allow or deny result to a partner action only. It remains an eligibility gate and does not consume the portable action-contract nonce store.
- Allowed means the partner may perform its own named action. Abraxas never executes the trade, payment, membership grant, wallet connection, or protocol call.
- Partners receive only allow or deny, a safe reason code, action binding, and expiry.
Canonical disclosure: Selective disclosure
Server side preflight
import { AbraxasPortableActionAdapter } from "@/lib/partner/portableActionContract";
const adapter = new AbraxasPortableActionAdapter({
partnerId: process.env.ABRAXAS_PARTNER_ID!,
policyId: process.env.ABRAXAS_POLICY_ID!,
policyVersion: 1,
requirePolicyVersion: true,
environment: "sandbox",
});
export async function grantMembership(receiptId: string) {
const contract = adapter.issueActionContract({
action_type: "grant_membership_access",
action_scope: "sandbox:membership_access",
});
if ("ok" in contract && contract.ok === false) {
return { allowed: false, reason: contract.reason };
}
const verified = await adapter.verifySignedReceipt(receiptId);
// allowed means your app may grant membership. Abraxas never grants it.
return adapter.preflight({ result: verified, contract });
}
export async function enableMarketAccess(receiptId: string) {
const contract = adapter.issueActionContract({
action_type: "enable_market_access",
action_scope: "sandbox:market_access",
});
if ("ok" in contract && contract.ok === false) {
return { allowed: false, reason: contract.reason };
}
const verified = await adapter.verifySignedReceipt(receiptId);
return adapter.preflight({ result: verified, contract });
}
export async function authorizeCheckout(receiptId: string) {
const contract = adapter.issueActionContract({
action_type: "authorize_checkout",
action_scope: "sandbox:checkout",
});
if ("ok" in contract && contract.ok === false) {
return { allowed: false, reason: contract.reason };
}
const verified = await adapter.verifySignedReceipt(receiptId);
return adapter.preflight({ result: verified, contract });
}
export async function partnerProtocolAction(receiptId: string, organizationBindingHash?: string) {
const contract = adapter.issueActionContract({
action_type: "partner_protocol_action",
action_scope: "sandbox:partner_protocol",
// Optional hashed organization/authorized-signer binding. Never a legal name or KYB file.
organization_subject_binding_hash: organizationBindingHash,
});
if ("ok" in contract && contract.ok === false) {
return { allowed: false, reason: contract.reason };
}
const verified = await adapter.verifySignedReceipt(receiptId);
return adapter.preflight({ result: verified, contract });
}
Studio: Integration Studio · Kit: Partner Integration Kit · Venue: Trading venue · Profiles: Venue profiles · Payment: Payment authorization · Networks: Mainnet readiness · EVM: EVM partner adapter · Keys: Receipt key lifecycle