# Invoice

Invoice API allows merchants to create and manage invoices

## Entities

### Invoice

`Invoice` entity represents single invoice

{% tabs %}
{% tab title="TypeScript" %}
Type may be imported as:

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

Type definition:

```typescript
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;
}
```

{% endtab %}
{% endtabs %}

### InvoiceStatus

`InvoiceStatus` is an enum, represents current status of invoice

{% tabs %}
{% tab title="TypeScript" %}
Enum may be imported as:

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

Type definition:

```typescript
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'
}
```

{% endtab %}
{% endtabs %}

### InvoicePayload

`InvoicePayload` represents custom data object attached to invoice

{% tabs %}
{% tab title="TypeScript" %}
Type may be imported as:

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

Type definition:

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

{% endtab %}
{% endtabs %}

## Methods

### Create invoice

{% tabs %}
{% tab title="TypeScript" %}
Request type definition:

```typescript
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:

```typescript
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:

```typescript
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);
    }
}
```

{% endtab %}
{% endtabs %}

### Get invoice by ID

{% tabs %}
{% tab title="TypeScript" %}

```typescript
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);
    }
}
```

{% endtab %}
{% endtabs %}

### Cancel invoice by ID

{% tabs %}
{% tab title="TypeScript" %}

```typescript
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);
    }
}
```

{% endtab %}
{% endtabs %}

### Get invoice from webhook

{% tabs %}
{% tab title="TypeScript" %}

```typescript
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)
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**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
{% endhint %}

## WebSocket Channels

### Invoice updates for specific client

{% tabs %}
{% tab title="TypeScript" %}

```typescript
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);
});
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
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](#get-invoice-from-webhook) instead
{% endhint %}

### Invoice status updates

{% tabs %}
{% tab title="TypeScript" %}

```typescript
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);
});
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
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](#invoice-updates-for-specific-client) channel instead, and subscribe to it before creating invoices
{% endhint %}

{% hint style="info" %}
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](#get-invoice-from-webhook) instead
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.simplepay.ai/docs/javascript-sdk/services/invoice.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
