Usage Examples
Every method returns ApiResponse<T>. Access the payload via .data, pagination via .meta.pagination.
import { EInvoice, EInvoiceApiError } from '@useyona/einvoice-js';
const client = new EInvoice({
apiKey: process.env.YONA_API_KEY!,
});Invoices — client.invoices
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateInvoiceParams) | ApiResponse<Invoice> |
get | get(id: string) | ApiResponse<Invoice> |
list | list(params?: ListInvoicesParams) | ApiResponse<Invoice[]> |
update | update(id: string, params: UpdateInvoiceParams) | ApiResponse<Invoice> |
delete | delete(id: string) | ApiResponse<{ deleted: boolean }> |
submit | submit(id: string) | ApiResponse<SubmitResult> |
batchSubmit | batchSubmit(invoiceIds: string[]) | ApiResponse<BatchSubmitResult> |
retry | retry(id: string) | ApiResponse<RetryResult> |
cancel | cancel(id: string, params: CancelInvoiceParams) | ApiResponse<Invoice> |
getStatus | getStatus(id: string) | ApiResponse<InvoiceStatusResult> |
queryStatus | queryStatus(id: string) | ApiResponse<InvoiceStatusResult> |
validate | validate(params: CreateInvoiceParams) | ApiResponse<ValidationResult> |
download | download(id: string) | ApiResponse<DownloadResult> |
getStatistics | getStatistics(params?: InvoiceStatisticsParams) | ApiResponse<InvoiceStatistics> |
getHsnCodes | getHsnCodes(params?: GetHsnCodesParams) | ApiResponse<HsnCode[]> |
getHsnCategories | getHsnCategories() | ApiResponse<HsnCategory[]> |
getResources | getResources() | ApiResponse<InvoiceResources> |
getResourceByType | getResourceByType(type: InvoiceResourceType) | ApiResponse<unknown[]> |
lookupTaxId | lookupTaxId(taxId: string) | ApiResponse<TaxpayerInfo> |
validateReference | validateReference(params: ValidateReferenceParams) | ApiResponse<ValidationResult> |
submitTaxReport | submitTaxReport(invoiceId: string, params: TaxReportParams) | ApiResponse<TaxReportResult> |
Create, submit, and check status
try {
const invoice = await client.invoices.create({
sellerId: 'c7a1d3e5-8f2b-4a6c-9d0e-1f2a3b4c5d6e',
buyerId: 'd8b2e4f6-9a3c-5b7d-0e1f-2a3b4c5d6e7f',
invoiceNumber: 'INV-2026-001',
invoiceDate: '2026-04-30',
dueDate: '2026-05-30',
currency: 'NGN',
lineItems: [
{
description: 'Software development services - April 2026',
hsnCode: '9983',
quantity: 80,
unitCode: 'HUR',
unitPrice: 15000,
taxPercent: 7.5,
},
],
paymentTerms: 'Net 30',
});
const submission = await client.invoices.submit(invoice.data.id);
const status = await client.invoices.getStatus(invoice.data.id);
} catch (err) {
if (err instanceof EInvoiceApiError) {
console.error(err.errorCode, err.message, err.errors);
}
}List with filters
const drafts = await client.invoices.list({
status: 'draft',
page: 1,
limit: 20,
sortOrder: 'DESC',
});
drafts.data.forEach(inv => {
console.log(inv.invoiceNumber, inv.payableAmount);
});Validate before creating
const validation = await client.invoices.validate({
sellerId: 'c7a1d3e5-8f2b-4a6c-9d0e-1f2a3b4c5d6e',
buyerId: 'd8b2e4f6-9a3c-5b7d-0e1f-2a3b4c5d6e7f',
invoiceNumber: 'INV-2026-002',
invoiceDate: '2026-04-30',
lineItems: [{
description: 'Annual ERP licensing fee',
hsnCode: '9984',
quantity: 1,
unitCode: 'EA',
unitPrice: 2500000,
taxPercent: 7.5,
}],
});
if (validation.data.valid) {
console.log('Totals:', validation.data.calculations);
}Sellers — client.sellers
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateSellerParams) | ApiResponse<Seller> |
get | get(id: string) | ApiResponse<Seller> |
list | list(params?: ListSellersParams) | ApiResponse<Seller[]> |
update | update(id: string, params: UpdateSellerParams) | ApiResponse<Seller> |
delete | delete(id: string) | ApiResponse<{ deleted: boolean }> |
bulkDelete | bulkDelete(ids: string[]) | ApiResponse<{ deleted: number }> |
verifyTin | verifyTin(id: string) | ApiResponse<TaxNumberVerificationResult> |
getVerificationStatus | getVerificationStatus(id: string) | ApiResponse<TaxNumberVerificationResult> |
search | search(query: string) | ApiResponse<SearchResult> |
const seller = await client.sellers.create({
partyName: 'Zenith Software Solutions Ltd',
email: 'billing@zenithsoftware.ng',
phoneNumber: '+2348012345678',
taxNumber: '31245678-0001',
postalAddress: {
line1: '14 Admiralty Way',
city: 'Lagos',
state: 'Lagos',
country: 'NG',
},
});
await client.sellers.verifyTin(seller.data.id);
const verification = await client.sellers.getVerificationStatus(seller.data.id);
const results = await client.sellers.search('Zenith');Buyers — client.buyers
Same methods as sellers. taxNumber is optional for buyers.
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateBuyerParams) | ApiResponse<Buyer> |
get | get(id: string) | ApiResponse<Buyer> |
list | list(params?: ListBuyersParams) | ApiResponse<Buyer[]> |
update | update(id: string, params: UpdateBuyerParams) | ApiResponse<Buyer> |
delete | delete(id: string) | ApiResponse<{ deleted: boolean }> |
bulkDelete | bulkDelete(ids: string[]) | ApiResponse<{ deleted: number }> |
verifyTin | verifyTin(id: string) | ApiResponse<TaxNumberVerificationResult> |
getVerificationStatus | getVerificationStatus(id: string) | ApiResponse<TaxNumberVerificationResult> |
search | search(query: string) | ApiResponse<SearchResult> |
const buyer = await client.buyers.create({
partyName: 'Kalu & Associates Ltd',
email: 'procurement@kaluassociates.ng',
phoneNumber: '+2349087654321',
taxNumber: '87654321-0001',
postalAddress: {
line1: '27 Wuse II District',
city: 'Abuja',
state: 'FCT',
country: 'NG',
},
});Billing — client.billing
| Method | Signature | Returns |
|---|---|---|
getAccount | getAccount() | ApiResponse<BillingAccount> |
checkBalance | checkBalance(accountId: string, credits: number) | ApiResponse<BalanceCheck> |
getPlans | getPlans(params?: ListPlansParams) | ApiResponse<SubscriptionPlan[]> |
getPlan | getPlan(code: string) | ApiResponse<SubscriptionPlan> |
getPackages | getPackages(params?: ListPackagesParams) | ApiResponse<CreditPackage[]> |
getPackage | getPackage(id: string) | ApiResponse<CreditPackage> |
getAllPlans | getAllPlans() | ApiResponse<Array<SubscriptionPlan | CreditPackage>> |
getActiveSubscription | getActiveSubscription() | ApiResponse<Subscription> |
getSubscriptionHistory | getSubscriptionHistory() | ApiResponse<Subscription[]> |
getSubscription | getSubscription(id: string) | ApiResponse<Subscription> |
createSubscription | createSubscription(params: CreateSubscriptionParams) | ApiResponse<Subscription> |
cancelSubscription | cancelSubscription(id: string, params?: CancelSubscriptionParams) | ApiResponse<Subscription> |
resumeSubscription | resumeSubscription(id: string) | ApiResponse<Subscription> |
changePlan | changePlan(id: string, params: ChangePlanParams) | ApiResponse<Subscription> |
purchaseCredits | purchaseCredits(params: PurchaseCreditsParams) | ApiResponse<PurchaseResult> |
getPayments | getPayments(params?: ListPaymentsParams) | ApiResponse<Payment[]> |
getTransactions | getTransactions(params?: ListTransactionsParams) | ApiResponse<CreditTransaction[]> |
transferCredits | transferCredits(params: TransferCreditsParams) | ApiResponse<TransferCreditsResult> |
getPaymentMethods | getPaymentMethods() | ApiResponse<PaymentMethod[]> |
addPaymentMethod | addPaymentMethod(params: AddPaymentMethodParams) | ApiResponse<{ customerId: string; setupUrl?: string }> |
removePaymentMethod | removePaymentMethod(provider: string, id: string) | ApiResponse<{ removed: boolean }> |
setDefaultPaymentMethod | setDefaultPaymentMethod(provider: string, params: { paymentMethodId: string }) | ApiResponse<{ customerId: string }> |
getUsageAnalytics | getUsageAnalytics(params?: UsageAnalyticsParams) | ApiResponse<UsageAnalytics> |
getConsumptionBreakdown | getConsumptionBreakdown() | ApiResponse<Record<string, unknown>> |
getAccountStats | getAccountStats(accountId: string) | ApiResponse<BillingAccountStats> |
getTransaction | getTransaction(id: string) | ApiResponse<CreditTransaction> |
subscribeAndPay | subscribeAndPay(params: SubscribeAndPayParams) | ApiResponse<SubscribeAndPayResult> |
getRenewalHistory | getRenewalHistory(params?: ListRenewalsParams) | ApiResponse<SubscriptionRenewal[]> |
getRenewalStats | getRenewalStats() | ApiResponse<RenewalStats> |
getCreditCosts | getCreditCosts() | ApiResponse<CreditCostEntry[]> |
const account = await client.billing.getAccount();
console.log(account.data.creditBalance);
const sufficient = await client.billing.checkBalance('1a2b3c4d-5e6f-7890-abcd-ef1234567890', 100);
const sub = await client.billing.createSubscription({
planCode: 'starter_monthly',
});
const purchase = await client.billing.purchaseCredits({
packageId: 'pkg_5000_credits',
currency: 'NGN',
});Organizations — client.organizations
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateOrganizationParams) | ApiResponse<Organization> |
list | list() | ApiResponse<Organization[]> |
get | get(id?: string) | ApiResponse<Organization> |
update | update(params: UpdateOrganizationParams) | ApiResponse<Organization> |
completeOnboarding | completeOnboarding(params: CompleteOnboardingParams) | ApiResponse<Organization> |
verifyTaxNumber | verifyTaxNumber(params: { taxNo: string }) | ApiResponse<Organization> |
sendPhoneVerification | sendPhoneVerification(params: { phoneNumber: string }) | ApiResponse<{ sent: boolean }> |
verifyPhone | verifyPhone(params: { otp: string }) | ApiResponse<Organization> |
getCreditPoolConfig | getCreditPoolConfig() | ApiResponse<CreditPoolConfig> |
updateCreditPoolConfig | updateCreditPoolConfig(params: Partial<CreditPoolConfig>) | ApiResponse<CreditPoolConfig> |
getChildren | getChildren() | ApiResponse<Organization[]> |
const org = await client.organizations.get();
await client.organizations.verifyTaxNumber({ taxNo: '31245678-0001' });
const children = await client.organizations.getChildren();
await client.organizations.updateCreditPoolConfig({
primaryCoversSecondary: true,
minimumReserve: 500,
});Webhooks — client.webhooks
Requires organizationId in client config.
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateWebhookParams) | ApiResponse<WebhookEndpoint> |
list | list(params?: PaginationParams) | ApiResponse<WebhookEndpoint[]> |
get | get(id: string) | ApiResponse<WebhookEndpoint> |
update | update(id: string, params: UpdateWebhookParams) | ApiResponse<WebhookEndpoint> |
delete | delete(id: string) | ApiResponse<{ deleted: boolean }> |
test | test(id: string) | ApiResponse<{ eventId: string }> |
listDeliveries | listDeliveries(webhookId: string, params?: ListDeliveriesParams) | ApiResponse<WebhookDelivery[]> |
retryDelivery | retryDelivery(deliveryId: string) | ApiResponse<{ retried: boolean }> |
const client = new EInvoice({
apiKey: process.env.YONA_API_KEY!,
organizationId: '9f8e7d6c-5b4a-3210-fedc-ba9876543210',
});
const webhook = await client.webhooks.create({
url: 'https://api.zenithsoftware.ng/webhooks/yona',
events: ['invoice.approved', 'invoice.rejected', 'invoice.failed'],
description: 'Production notifications',
});
await client.webhooks.test(webhook.data.id);
const deliveries = await client.webhooks.listDeliveries(webhook.data.id);Webhook verification
import { verifyWebhook } from '@useyona/einvoice-js/webhooks';
const event = verifyWebhook(rawBody, requestHeaders, process.env.WEBHOOK_SECRET!);
switch (event.eventType) {
case 'invoice.approved':
handleApproved(event.data);
break;
case 'invoice.rejected':
handleRejected(event.data);
break;
case 'invoice.failed':
handleFailed(event.data);
break;
}API Keys — client.apiKeys
Requires organizationId.
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateApiKeyParams) | ApiResponse<ApiKeyWithKey> |
list | list(params?: PaginationParams) | ApiResponse<ApiKey[]> |
get | get(id: string) | ApiResponse<ApiKey> |
revoke | revoke(id: string) | ApiResponse<{ revoked: boolean }> |
rotate | rotate(id: string) | ApiResponse<RotateApiKeyResult> |
updateRole | updateRole(id: string, params: UpdateApiKeyRoleParams) | ApiResponse<{ updated: boolean }> |
getPermissions | getPermissions(id: string) | ApiResponse<ApiKeyPermissions> |
const key = await client.apiKeys.create({
mode: 'sandbox',
name: 'CI/CD Pipeline Key',
});
const rotated = await client.apiKeys.rotate('7a8b9c0d-1e2f-3456-7890-abcdef123456');
await client.apiKeys.revoke('7a8b9c0d-1e2f-3456-7890-abcdef123456');🚨 Store keys immediately
key.data.key and rotated.data.newApiKey.key are returned only once.
Users — client.users
Requires organizationId.
| Method | Signature | Returns |
|---|---|---|
list | list(params?: ListUsersParams) | ApiResponse<User[]> |
get | get(id: string) | ApiResponse<User> |
getMe | getMe() | ApiResponse<User> |
update | update(id: string, params: UpdateUserParams) | ApiResponse<User> |
updateRole | updateRole(id: string, params: { roleId: string }) | ApiResponse<{ updated: boolean }> |
updateStatus | updateStatus(id: string, params: { status: UserStatus }) | ApiResponse<User> |
getPermissions | getPermissions(id: string) | ApiResponse<UserPermissions> |
addPermissions | addPermissions(id: string, params: { permissions: string[] }) | ApiResponse<User> |
removePermissions | removePermissions(id: string, params: { permissions: string[] }) | ApiResponse<User> |
sendPhoneVerification | sendPhoneVerification(id: string, params: SendPhoneVerificationParams) | ApiResponse<{ sent: boolean }> |
verifyPhone | verifyPhone(id: string, params: VerifyPhoneOtpParams) | ApiResponse<User> |
const users = await client.users.list();
const me = await client.users.getMe();
await client.users.updateRole('f1e2d3c4-b5a6-7890-1234-567890abcdef', { roleId: 'role_admin' });Invitations — client.invitations
Requires organizationId except for verify and accept.
| Method | Signature | Returns |
|---|---|---|
create | create(params: CreateInvitationParams) | ApiResponse<Invitation> |
list | list(params?: ListInvitationsParams) | ApiResponse<Invitation[]> |
resend | resend(id: string) | ApiResponse<Invitation> |
revoke | revoke(id: string) | ApiResponse<Invitation> |
verify | verify(params: VerifyInvitationParams) | ApiResponse<InvitationVerification> |
accept | accept(params: AcceptInvitationParams) | ApiResponse<AcceptInvitationResult> |
await client.invitations.create({
email: 'colleague@zenithsoftware.ng',
roleId: 'role_member',
});Roles — client.roles
Requires organizationId.
| Method | Signature | Returns |
|---|---|---|
list | list() | ApiResponse<Role[]> |
create | create(params: CreateRoleParams) | ApiResponse<Role> |
get | get(roleId: string) | ApiResponse<RoleDetails> |
update | update(roleId: string, params: UpdateRoleParams) | ApiResponse<Role> |
delete | delete(roleId: string) | ApiResponse<null> |
getAvailablePermissions | getAvailablePermissions() | ApiResponse<AvailablePermissions> |
const roles = await client.roles.list();
const permissions = await client.roles.getAvailablePermissions();
const customRole = await client.roles.create({
name: 'invoice_submitter',
displayName: 'Invoice Submitter',
description: 'Can create and submit invoices only',
permissions: ['invoice.create', 'invoice.submit', 'invoice.read'],
});B2B2B Partner Helpers
Methods on the EInvoice client instance for multi-tenant operations.
| Method | Description |
|---|---|
forOrganization(orgId) | Returns a new client scoped to a child org (same API key). For API keys, users, webhooks. |
forApiKey(apiKey, orgId?) | Returns a new client with a different API key. For invoices, sellers, buyers, billing. |
createOrganizationWithApiKey(orgParams, keyParams) | Creates a child org and its first API key in one call. |
const partner = new EInvoice({
apiKey: 'sk_live_partner_key_here',
organizationId: '9f8e7d6c-5b4a-3210-fedc-ba9876543210',
});
const { organization, apiKey } = await partner.createOrganizationWithApiKey(
{ businessName: 'Lagos Tech Innovations Nigeria Ltd', email: 'admin@lagostech.ng' },
{ mode: 'production', name: 'lagostech-primary-key' },
);
const childClient = partner.forApiKey(apiKey.key, organization.id);
const seller = await childClient.sellers.create({
partyName: 'Lagos Tech Innovations Nigeria Ltd',
email: 'billing@lagostech.ng',
phoneNumber: '+2348023456789',
taxNumber: '45678901-0001',
postalAddress: { line1: '3 Victoria Island', city: 'Lagos', country: 'NG' },
});
const childAdmin = partner.forOrganization(organization.id);
await childAdmin.apiKeys.list();
await childAdmin.users.list();🚨 Store the key immediately
apiKey.key is returned only once. It cannot be retrieved after this response.
Error handling pattern
This pattern applies to every SDK method across all services. See Error Handling for the full error class reference.
import {
EInvoice,
EInvoiceApiError,
EInvoiceRateLimitError,
EInvoiceTimeoutError,
EInvoiceConfigError,
} from '@useyona/einvoice-js';
const client = new EInvoice({ apiKey: process.env.YONA_API_KEY! });
try {
const invoice = await client.invoices.create({
sellerId: 'c7a1d3e5-8f2b-4a6c-9d0e-1f2a3b4c5d6e',
buyerId: 'd8b2e4f6-9a3c-5b7d-0e1f-2a3b4c5d6e7f',
invoiceNumber: 'INV-2026-001',
invoiceDate: '2026-04-30',
lineItems: [{
description: 'API integration services',
hsnCode: '9983',
quantity: 1,
unitCode: 'EA',
unitPrice: 750000,
taxPercent: 7.5,
}],
});
} catch (err) {
if (err instanceof EInvoiceRateLimitError) {
await sleep(err.retryAfter * 1000);
// retry
} else if (err instanceof EInvoiceApiError) {
switch (err.statusCode) {
case 400:
if (err.errorCode === 'BIZ001') {
handleInsufficientCredits();
} else {
handleValidation(err.errorCode, err.errors);
}
break;
case 404:
handleNotFound(err.message);
break;
case 409:
handleConflict(err.message);
break;
}
} else if (err instanceof EInvoiceTimeoutError) {
retryWithBackoff(err.timeoutMs);
} else if (err instanceof EInvoiceConfigError) {
fixConfiguration(err.message);
}
}Last updated on