๐ŸงพInvoice

Invoice API allows merchants to create and manage invoices

Entities

Invoice

Invoice entity represents single invoice

Type may be imported as:

import type { Invoice } from '@simplepay-ai/api-client';

Type definition:

interface Invoice {
    /**
     * Invoice ID
     *
     * @example '6ef3cc15-24ae-4192-9744-a9017ed153cc'
     */
    id: string;

    /**
     * Parent invoice ID
     *
     * @example 'dd90187e-d1d0-405f-bf2f-242c15403297'
     */
    parentId: string | null;

    /**
     * ID of end customer, who makes the payment
     *
     * @example '46778124-f9e0-4eba-ae1a-ecd5c0d9e90b'
     */
    clientId: string;

    /**
     * Wallet address from which customer made payment
     *
     * @example '0x41ce73496136A0072013B9187550e30841eDeD74'
     */
    from: string;

    /**
     * Wallet address of payment recipient
     *
     * @example '0x1105F97fBAB9674Ef069331F2b48E9B870ed9Adc'
     */
    to: string;

    /**
     * Invoice amount in cryptocurrency
     *
     * @example '501.723934'
     */
    amount: string;

    /**
     * Invoice price in fiat currency
     *
     * @example '500.00'
     */
    price: string;

    /**
     * Invoice type
     *
     * @example 'payment'
     */
    type: 'payment';

    /**
     * Invoice status
     *
     * @example 'success'
     */
    status: InvoiceStatus;

    /**
     * Transaction hash
     *
     * @example '0xe9e91f1ee4b56c0df2e9f06c2b8c27c6076195a88a7b8537ba8313d80e6f124e'
     */
    txHash: string | null;

    /**
     * Block number
     *
     * @example 1000000
     */
    txBlock: number | null;

    /**
     * Invoice creation timestamp
     *
     * @example '2024-07-31T00:48:53Z'
     */
    createdAt: string;

    /**
     * Invoice update timestamp
     *
     * @example '2024-07-31T00:49:28Z'
     */
    updatedAt: string;

    /**
     * Invoice expiration timestamp
     *
     * @example '2024-07-31T01:14:28Z'
     */
    expireAt: string;

    /**
     * Invoice cryptocurrency
     */
    cryptocurrency: Cryptocurrency;

    /**
     * Invoice network
     */
    network: Network;

    /**
     * Invoice fiat currency
     */
    currency: Currency;

    /**
     * Custom data attached to invoice
     *
     * @example {
     *   someKey: 'someValue'
     * }
     */
    payload: InvoicePayload | null;
}

InvoiceStatus

InvoiceStatus is an enum, represents current status of invoice

Enum may be imported as:

import { InvoiceStatus } from '@simplepay-ai/api-client';

Type definition:

enum InvoiceStatus {
    /**
     * Invoice created and preparing for future processing
     */
    Created = 'created',

    /**
     * System is ready for accepting payment
     *
     * End customer allowed to send cryptocurrency
     */
    Processing = 'processing',

    /**
     * Transaction found in blockchain
     *
     * System awaiting for some amount of new blocks to be mined for safety
     *
     * `txHash` and `txBlock` fields in invoice was filled on this status
     */
    Confirming = 'confirming',

    /**
     * Invoice succeeded
     *
     * Paid service may be granted to end customer on this status
     */
    Success = 'success',

    /**
     * Invoice rejected
     *
     * Transaction was failed, or another issue was happen
     */
    Rejected = 'rejected',

    /**
     * Invoice canceled
     *
     * By end customer or merchant
     */
    Canceled = 'canceled',

    /**
     * Invoice expired
     *
     * End customer does not send transaction in time
     */
    Expired = 'expired'
}

InvoicePayload

InvoicePayload represents custom data object attached to invoice

Type may be imported as:

import type { InvoicePayload } from '@simplepay-ai/api-client';

Type definition:

interface InvoicePayload {
    [key: string]: any;
}

Methods

Create invoice

Request type definition:

type InvoiceCreateRequest = {
    /**
     * Application ID
     *
     * @example 'deae9fe3-9f00-4c18-8b24-dbc86e142128'
     */
    appId: string;

    /**
     * Invoice type
     *
     * @example 'payment'
     */
    type: 'payment';

    /**
     * Parent invoice ID
     *
     * @example 'dd90187e-d1d0-405f-bf2f-242c15403297'
     */
    parentId: string | null;

    /**
     * ID of end customer, who makes the payment
     *
     * @example '46778124-f9e0-4eba-ae1a-ecd5c0d9e90b'
     */
    clientId: string;

    /**
     * Wallet address from which customer made payment
     *
     * @example '0x41ce73496136A0072013B9187550e30841eDeD74'
     */
    from: string;

    /**
     * Cryptocurrency symbol
     *
     * @example 'USDT'
     */
    cryptocurrency: string;

    /**
     * Network symbol
     *
     * @example 'ethereum'
     */
    network: string;

    /**
     * Fiat currency symbol (ISO 4217 alphabetic code)
     *
     * @example 'USD'
     * @see https://en.wikipedia.org/wiki/ISO_4217
     */
    currency: string;

    /**
     * Price in fiat currency
     *
     * @example 500
     */
    price: number;

    /**
     * Custom data attached to invoice
     *
     * @example {
     *   someKey: 'someValue'
     * }
     */
    payload?: InvoicePayload | null;
};

Validation errors type definition:

type InvoiceCreateErrors = {
    appId?: 'required' | 'uuid4' | 'invalid';
    type?: 'required' | 'oneof';
    parentId?: 'uuid4';
    clientId?: 'required' | 'ascii' | 'max' | 'invalid';
    from?: 'required' | 'alphanum' | 'invalid';
    cryptocurrency?: 'required' | 'alpha' | 'uppercase' | 'invalid';
    network?: 'required' | 'alpha' | 'lowercase' | 'invalid';
    currency?: 'required' | 'alpha' | 'uppercase' | 'invalid';
    price?: 'required' | 'numeric' | 'gte' | 'lte';
    payload?: 'len';
};

Method call example:

import type {
    InvoiceCreateRequest,
    InvoiceCreateErrors,
    HttpError,
    ValidationError
} from '@simplepay-ai/api-client';

try {
    const request: InvoiceCreateRequest = {
        // ID of your application, obtained from console
        appId: 'c4affb7c-586c-48a2-803b-8379b1e1e8b2',

        // Invoice type
        type: 'payment',

        // ID of end customer, who makes the payment
        clientId: '46778124-f9e0-4eba-ae1a-ecd5c0d9e90b',

        // Wallet address from which customer made payment
        from: '0x41ce73496136A0072013B9187550e30841eDeD74',

        // Cryptocurrency symbol
        cryptocurrency: 'USDT',

        // Network symbol
        network: 'ethereum',

        // Fiat currency symbol (ISO 4217 alphabetic code)
        currency: 'USD',

        // Price in fiat currency
        price: 500
    };

    const invoice = await api.invoice.create(request);

    console.debug(invoice);
} catch (e) {
    if (e instanceof ValidationError) {
        const error = e as ValidationError<InvoiceCreateErrors>;

        console.error(error.errors);
    }

    if (e instanceof HttpError) {
        const error = e as HttpError;

        console.error(error.code);
    }
}

Get invoice by ID

import type { HttpError } from '@simplepay-ai/api-client';

try {
    const invoiceId = '6ef3cc15-24ae-4192-9744-a9017ed153cc';

    const invoice = await api.invoice.get(invoiceId);

    console.debug(invoice);
} catch (e) {
    if (e instanceof HttpError) {
        const error = e as HttpError;

        console.error(error.code);
    }
}

Cancel invoice by ID

import type { HttpError } from '@simplepay-ai/api-client';

try {
    const invoiceId = '6ef3cc15-24ae-4192-9744-a9017ed153cc';

    const invoice = await api.invoice.cancel(invoiceId);

    console.debug(invoice);
} catch (e) {
    if (e instanceof HttpError) {
        const error = e as HttpError;

        console.error(error.code);
    }
}

Get invoice from webhook

try {
    // This should be set to a raw body of webhook request
    const body: string = '{"id":"...",...}';

    // This should be set to `X-Signature` header value from webhook request
    const signature: string = '...';

    // To find out how to extract request body and header,
    // read the documentation for framework that you use

    const invoice = api.invoice.fromWebhook(body, signature);

    console.debug(invoice);
} catch (e) {
    console.error(e.message)
}

This method requires API key to be set, and should only be called from server-side

Exposing API key to third-parties gives them ability to bypass payment step and access paid functions of your application

WebSocket Channels

Invoice updates for specific client

import { InvoiceStatus } from '@simplepay-ai/api-client';

const appId = 'c4affb7c-586c-48a2-803b-8379b1e1e8b2';
const clientId = '6ef3cc15-24ae-4192-9744-a9017ed153cc';

const channel = ws.appClientInvoice(appId, clientId);

channel.on(InvoiceStatus.Processing, (invoice) => {
    // System is ready for accepting payment
    // End customer allowed to send cryptocurrency

    console.debug(invoice);
});

channel.on(InvoiceStatus.Confirming, (invoice) => {
    // Transaction found in blockchain
    // System awaiting for some amount of new blocks to be mined for safety
    // `txHash` and `txBlock` fields in invoice was filled on this status

    console.debug(invoice);
});

channel.on(InvoiceStatus.Success, (invoice) => {
    // Invoice succeeded

    console.debug(invoice);
});

channel.on(InvoiceStatus.Rejected, (invoice) => {
    // Invoice rejected
    // Transaction was failed, or another issue was happen

    console.debug(invoice);
});

channel.on(InvoiceStatus.Canceled, (invoice) => {
    // Invoice canceled
    // By end customer or merchant

    console.debug(invoice);
});

channel.on(InvoiceStatus.Expired, (invoice) => {
    // Invoice expired
    // End customer does not send transaction in time

    console.debug(invoice);
});

This channel intended to use in frontend applications for informing end customers about status of their payments. Do not use it as handler for crediting accounts or providing them access to paid features of your application, use Webhooks instead

Invoice status updates

import { InvoiceStatus } from '@simplepay-ai/api-client';

const invoiceId = '6ef3cc15-24ae-4192-9744-a9017ed153cc';

const channel = ws.invoice(invoiceId);

channel.on(InvoiceStatus.Processing, (invoice) => {
    // System is ready for accepting payment
    // End customer allowed to send cryptocurrency

    console.debug(invoice);
});

channel.on(InvoiceStatus.Confirming, (invoice) => {
    // Transaction found in blockchain
    // System awaiting for some amount of new blocks to be mined for safety
    // `txHash` and `txBlock` fields in invoice was filled on this status

    console.debug(invoice);
});

channel.on(InvoiceStatus.Success, (invoice) => {
    // Invoice succeeded

    console.debug(invoice);
});

channel.on(InvoiceStatus.Rejected, (invoice) => {
    // Invoice rejected
    // Transaction was failed, or another issue was happen

    console.debug(invoice);
});

channel.on(InvoiceStatus.Canceled, (invoice) => {
    // Invoice canceled
    // By end customer or merchant

    console.debug(invoice);
});

channel.on(InvoiceStatus.Expired, (invoice) => {
    // Invoice expired
    // End customer does not send transaction in time

    console.debug(invoice);
});

Some events may be lost if they happen in period between invoice creation and subscription to this channel.

In most cases it's better to use appClientInvoice channel instead, and subscribe to it before creating invoices

This channel intended to use in frontend applications for informing end customers about status of their payments. Do not use it as handler for crediting accounts or providing them access to paid features of your application, use Webhooks instead

Last updated