Data Models
These models mirror the public types and serializers used by the current @primevault/js-api-sdk. Optional properties are marked with ?. Unless explicitly stated otherwise, IDs and decimal amounts are strings.
Cursor list response
Transaction, vault, contact, and bank-account list methods return the same cursor envelope.
interface CursorListResponse<T> {
results: T[];
nextCursor?: string | null;
hasNext?: boolean;
}Transfer parties
enum TransferPartyType {
CONTACT = "CONTACT",
VAULT = "VAULT",
EXTERNAL_ADDRESS = "EXTERNAL_ADDRESS",
EXTERNAL_BANK_ACCOUNT = "EXTERNAL_BANK_ACCOUNT",
BANK_ACCOUNT = "BANK_ACCOUNT",
}
interface TransferPartyData {
type: TransferPartyType | string;
id?: string;
name?: string;
address?: string;
provider?: string;
bankDetails?: BankDetails;
chain?: string;
paymentRail?: string;
}
interface BankDetails {
bankAccountId?: string;
bankName?: string;
bankCode?: string;
beneficiaryName?: string;
accountName?: string;
accountNumber?: string;
accountNumberMasked?: string;
routingNumber?: string;
paymentRail?: string;
bankAddress?: string;
beneficiaryAddress?: string;
swiftCode?: string;
swiftBic?: string;
iban?: string;
country?: string;
}Party type | Identification |
|---|---|
VAULT, CONTACT, BANK_ACCOUNT | Use the organization-scoped resource id. |
EXTERNAL_ADDRESS | Use address and chain; do not put the address in id. |
EXTERNAL_BANK_ACCOUNT | Use the applicable bankDetails and payment-rail fields. |
A party is the sender or receiver. Its id identifies that endpoint; input.vaultId and output.vaultId select the fiat accounts. Use IDs from your organization. Parties do not accept subOrgId.
Asset and chain
interface Asset {
name: string;
symbol: string;
blockChain: string;
logoURL?: string;
details?: unknown;
}
interface ChainData {
value: string;
label: string;
}details is chain-specific. Use symbol plus blockChain to identify an asset representation.
Vault
enum VaultType {
EXCHANGE = "EXCHANGE",
DEFAULT = "DEFAULT",
GAS = "GAS",
}
interface Vault {
id: string;
orgId: string;
subOrgId?: string;
vaultName: string;
vaultType: VaultType;
asset?: string | null;
wallets: Array<{
id: string;
blockchain: string;
address?: string;
publicKey?: string;
}>;
walletsGenerated: boolean;
createdAt: string;
updatedAt: string;
isDeleted: boolean;
}A vault is like an account. asset: "NGN" means it holds NGN. Set input.vaultId or output.vaultId to that account's ID. A null or missing asset does not identify a currency account.
walletsGenerated describes blockchain-wallet readiness after creation and approval; use returned bank deposit instructions for fiat funding.
Contact
enum ContactStatus {
PENDING = "PENDING",
APPROVED = "APPROVED",
DECLINED = "DECLINED",
}
interface Contact {
id: string;
orgId: string;
subOrgId?: string;
name: string;
blockChain: string;
address: string;
status: ContactStatus;
isSmartContractAddress: boolean;
tags?: string[];
createdById: string;
isSanctioned: boolean;
externalId?: string;
createdAt: string;
updatedAt: string;
isDeleted: boolean;
assetList?: string[];
}Bank account
enum BankAccountStatus {
PENDING = "PENDING",
APPROVED = "APPROVED",
DECLINED = "DECLINED",
}
interface BankAccount {
id: string;
orgId: string;
subOrgId?: string;
orgEntityId: string;
createdById: string;
createdAt: string;
updatedAt: string;
isDeleted: boolean;
status: BankAccountStatus;
accountNumber?: string;
accountName?: string;
routingNumber?: string;
clientBankAccountId?: string;
paymentMethod?: string;
bankName?: string;
streetLine?: string;
city?: string;
state?: string;
postalCode?: string;
country?: string;
}Bank-account fields can contain sensitive financial data. Avoid including them in application logs or analytics payloads.
Transaction
interface Transaction {
id: string;
orgId: string;
vaultId: string;
status: TransactionStatus | string;
transactionType: TransactionType | string;
category: TransactionCategory | string;
subCategory: TransactionSubCategory | string;
createdAt: string;
updatedAt: string;
isDeleted: boolean;
amount: string;
txHash?: string;
error?: string;
externalId?: string;
createdById?: string;
fees?: Fees;
memo?: string;
txnSignature?: string;
txnSignatureData?: Record<string, unknown>;
output?: TransactionOutput;
amountInUSD?: string;
nonce?: number;
dAppId?: string;
source?: TransactionSourceData;
destination?: TransactionSourceData;
intent?: TransactionIntentRequest;
quoteResponse?: QuoteResponseItem;
depositInstructions?: DepositInstructions;
operations?: TransactionOperation[];
balanceChanges?: TransactionOperationBalanceChanges | null;
blockChain?: string;
asset?: string;
/** Deprecated: use destination.address. */
toAddress?: string;
/** Deprecated: use destination.name. */
toAddressName?: string;
/** Deprecated: use destination.id. */
toVaultId?: string;
/** Deprecated: use source.address. */
sourceAddress?: string;
}Transaction enums
enum TransactionType {
INCOMING = "INCOMING",
OUTGOING = "OUTGOING",
}
enum TransactionCategory {
TRANSFER = "TRANSFER",
SWAP = "SWAP",
TOKEN_TRANSFER = "TOKEN_TRANSFER",
TOKEN_APPROVAL = "TOKEN_APPROVAL",
CONTRACT_CALL = "CONTRACT_CALL",
STAKE = "STAKE",
REVOKE_TOKEN_ALLOWANCE = "REVOKE_TOKEN_ALLOWANCE",
ON_RAMP = "ON_RAMP",
OFF_RAMP = "OFF_RAMP",
DELEGATE_RESOURCE = "DELEGATE_RESOURCE",
}
enum TransactionSubCategory {
INCOMING_TRANSFER = "INCOMING_TRANSFER",
EXTERNAL_TRANSFER = "EXTERNAL_TRANSFER",
INTERNAL_TRANSFER = "INTERNAL_TRANSFER",
LIMIT_TRADE = "LIMIT_TRADE",
MARKET_TRADE = "MARKET_TRADE",
APPROVE_TOKEN_ALLOWANCE = "APPROVE_TOKEN_ALLOWANCE",
CUSTOM_MESSAGE = "CUSTOM_MESSAGE",
CONTRACT_CALL = "CONTRACT_CALL",
STAKE = "STAKE",
UNSTAKE = "UNSTAKE",
CLAIM = "CLAIM",
ON_RAMP = "ON_RAMP",
OFF_RAMP = "OFF_RAMP",
}
enum TransactionStatus {
DRAFT = "DRAFT",
PENDING = "PENDING",
APPROVED = "APPROVED",
COMPLETED = "COMPLETED",
FAILED = "FAILED",
DECLINED = "DECLINED",
SUBMITTED = "SUBMITTED",
SIGNED = "SIGNED",
WAITING_CONFIRMATION = "WAITING_CONFIRMATION",
}Transaction operations and balance changes
enum TransactionOperationType {
DEPOSIT = "DEPOSIT",
TRADE = "TRADE",
TRANSFER = "TRANSFER",
WITHDRAW = "WITHDRAW",
}
enum TransactionOperationStatus {
PENDING = "PENDING",
PROCESSING = "PROCESSING",
COMPLETED = "COMPLETED",
FAILED = "FAILED",
SKIPPED = "SKIPPED",
CANCELLED = "CANCELLED",
REVERSED = "REVERSED",
}
interface TransactionOperationBalanceChange {
party: TransferPartyData | null;
asset: string;
amount: string;
chain?: string;
paymentRail?: string;
}
interface TransactionOperationBalanceChanges {
changes: TransactionOperationBalanceChange[];
}
interface TransactionOperation {
source: TransferPartyData | null;
destination: TransferPartyData | null;
balanceChanges: TransactionOperationBalanceChanges | null;
sequence: number;
type: TransactionOperationType | string;
status: TransactionOperationStatus | string;
provider?: string;
}Use operation sequence to preserve workflow order. Operation-level balanceChanges describes that leg; top-level transaction balanceChanges describes the aggregate transaction view when present.
Intent and quote
interface IntentAsset {
asset: string;
amount?: string | null;
vaultId?: string;
}
interface TransactionIntentRequest {
input: IntentAsset;
output: IntentAsset;
source: TransferPartyData;
destination: TransferPartyData;
}
interface GetQuoteRequest {
intent: TransactionIntentRequest;
}
interface TransactionExecuteIntentRequest {
intent?: TransactionIntentRequest | null;
quoteId?: string | null;
externalId?: string;
memo?: string;
}
interface Fees {
amount: string;
asset: string;
amountInFiat?: string;
}
interface QuoteResponseItem {
quoteId: string;
rate?: string | null;
fees?: Fees | null;
input?: IntentAsset;
output?: IntentAsset;
}
interface QuoteResponse {
quotes: QuoteResponseItem[];
}Think of an intent as a payment order: input is what you spend; output is what you receive. For a quote, supply both assets and exactly one amount, as a decimal string. Set chain or paymentRail on the source or destination.
Get a quote with getQuote({ intent }), then execute its quoteId with createTransactionFromIntent({ quoteId, externalId, memo }). Quotes may include input and output amounts. Do not send category, routeAccounts, or subOrgId. Omitted fields stay omitted; quote-only execution sends intent: null.
Deposit instructions
interface DepositInstructions {
type?: TransferPartyType | string;
paymentRail?: string;
bankDetails?: BankDetails;
asset?: string;
address?: string;
chain?: string;
memo?: string;
}
type GetVaultDepositInstructionsRequest = {
asset: string;
} & (
| { chain: string; paymentRail?: never }
| { chain?: never; paymentRail: string }
);
interface VaultDepositInstructionsResponse {
results: DepositInstructions[];
}Deposit instructions are like bank transfer details. Request asset plus exactly one of paymentRail or chain. Vault instructions return a results list; transaction instructions return one optional object. Quotes do not include them. Use the returned details exactly.
Fees and balances
interface FeeData {
expectedFeeInAsset: string;
asset: string;
expectedFeeInUSD: string;
baseFee?: string;
priorityFee?: string;
}
interface EstimatedFeeResponse {
high: FeeData;
medium: FeeData;
low: FeeData;
}
interface BalanceResponse {
[asset: string]: {
[chain: string]: string;
};
}
interface DetailedBalance {
symbol: string;
balance: string;
name?: string;
chain?: string;
tokenAddress?: string;
balanceInUSD?: string;
price?: string;
}
type DetailedBalanceResponse = DetailedBalance[];Approval models
enum ApprovalAction {
APPROVE = "approve",
REJECT = "reject",
DECLINE = "reject",
}
interface GetApprovalMessageResponse {
approvalId: string;
message: string;
changeRequestId?: string;
entityId?: string;
}
interface ApprovalActionResponse {
success: boolean;
status?: string;
id?: string;
entityId?: string;
}Webhook event envelope
interface WebhookEvent {
event:
| "TRANSACTION_STATUS_CHANGED"
| "TRANSACTION_OPERATION_STATUS_CHANGED";
version: "2.0.0";
eventId: string;
data: {
transaction?: Transaction;
transactionOperation?: TransactionOperation;
};
}