Developers
Add user-controlled authority to your agent app.
Create an application and begin integrating immediately. Use Test mode while building, then request Live access for your production deployment.
The application keeps execution. The user keeps authority.
Install the SDKs
Add the server-side Partner SDK and the Gate SDK to the infrastructure that owns your provider credentials.
npm install @receiptprotocol/partner-sdk
npm install @receiptprotocol/gate-sdkHow it works
One authority boundary between user intent and provider entry.
- 01
Register your application
Create a Test application and issue server-side credentials.
- 02
Send the user to Receipt
Let the user review and authorize a scoped, revocable mandate.
- 03
Submit an exact action
Bind the amount, counterparty, provider, and material action fields.
- 04
Enforce the one-time admission
Claim the signed admission before your infrastructure calls the provider.
- 05
Report and reconcile the result
Report success, failure, or uncertainty and reconcile the original action once.
Build your first governed action
Use the Partner SDK to submit the action and the Gate SDK to enforce the one-time admission before provider entry.
import { ReceiptPartnerClient } from "@receiptprotocol/partner-sdk";
import { ReceiptAuthorityGate } from "@receiptprotocol/gate-sdk";
const receipt = new ReceiptPartnerClient({
baseUrl: process.env.RECEIPT_PARTNER_BASE_URL!,
partnerKey: process.env.RECEIPT_PARTNER_KEY!,
});
// Submit one exact action against the active mandate.
const proposal = await receipt.createProposal({
partner_reference: process.env.RECEIPT_PARTNER_REFERENCE!,
principal_reference: principalReference,
agent_connection_reference: agentConnectionReference,
mandate_reference: mandateReference,
expected_mandate_version: mandateVersion,
action_profile_reference: "reference_economic_action.v1",
action_profile_version: 1,
proposed_action: action,
occurrence_id: action.occurrence_id,
idempotency_key: `proposal:${action.occurrence_id}`,
proposal_expires_at: action.action_expires_at,
});
if (proposal.policy_decision !== "permitted" || !proposal.execution_admission) {
throw new Error(`not_permitted:${proposal.policy_decision}`);
}
// Enforce the one-time admission before any provider call.
const signingKeys = await receipt.getSigningKeys();
const gate = new ReceiptAuthorityGate({
authorityBaseUrl: process.env.RECEIPT_PARTNER_BASE_URL!,
partnerKey: process.env.RECEIPT_PARTNER_KEY!,
partnerReference: process.env.RECEIPT_PARTNER_REFERENCE!,
environment: "sandbox",
agentConnectionReference,
trustedAdmissionKeys: Object.fromEntries(
signingKeys.keys
.filter((key) => key.environment === "sandbox" && key.purpose === "execution_admission")
.map((key) => [key.key_id, key.public_jwk]),
),
});
// Gate claims the admission once, invokes your callback once,
// and reports the result. Your provider credentials never leave here.
const executed = await gate.executeOnce({
admission: proposal.execution_admission,
action,
providerReference: "provider:synthetic",
invoke: () => callYourProvider(action),
classifyResult: (report) => ({ event_type: "complete", report }),
});