> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/common/monetization/iap/in-app-purchase.md).

# In-app purchases

This is a one-time payment SDK used for products that are completed with a single purchase, like consumables and non-consumables. For the service introduction and console setup method, see [In-app Purchase Introduction](https://developers-apps-in-toss.toss.im/guide/monetization/in-app-payment).

{% hint style="info" %}
**BaseURL**

`https://apps-in-toss-api.toss.im`
{% endhint %}

{% hint style="info" %}
**mTLS certificate is required for server-to-server communication**

The order status inquiry API for in-app purchases is a server-to-server communication called from the partner server to the App in Toss server. For security, set up an mTLS certificate on the server before calling it. For how to issue a certificate, refer to the mTLS certificate issuance method.
{% endhint %}

Please follow the sequence below for the integration flow.

1. [Get product list](#getproductitemlist) — `getProductItemList`
2. [Make a payment request](#createonetimepurchaseorder) — `createOneTimePurchaseOrder`
3. [Restore pending orders](#getpendingorders) — `getPendingOrders`, `completeProductGrant`
4. [Check order status](#getcompletedorrefundedorders) — `getCompletedOrRefundedOrders` or [Order status lookup API](#주문-상태-조회-api)

{% hint style="info" %}
**Caution**

* SDK **version 1.1.3 or later**Please use.
  * From SDK version 1.1.3, **the product grant completion process**has been added, changing the function interface.
* SDK **version 1.2.2**and later, **purchase restoration feature**has been added.
* **Make sure to integrate it so that in-app purchase products can remain granted even if the user's device changes.**
  * Please use the native storage feature.
  * Please use Toss login integration and the in-app purchase status inquiry API.
* To use the in-app purchase status inquiry API, you must first integrate Toss login.
  {% endhint %}

***

### IAP object

`IAP`is an object that groups in-app purchase-related functions.

{% hint style="info" %}
**Caution**

Supported starting from Toss app version 5.219.0. In versions that do not support in-app purchases, `undefined`is returned.
{% endhint %}

**Signature**

```typescript
IAP {
  getProductItemList: typeof getProductItemList;
  createOneTimePurchaseOrder: typeof createOneTimePurchaseOrder;
  getPendingOrders: typeof getPendingOrders;
  getCompletedOrRefundedOrders: typeof getCompletedOrRefundedOrders;
  completeProductGrant: typeof completeProductGrant;
}
```

**Properties**

* getProductItemListtypeof getProductItemList

  This is a function that retrieves a list of products that can be purchased with in-app purchases. For details, see [getProductItemList](#getproductitemlist).
* createOneTimePurchaseOrdertypeof createOneTimePurchaseOrder

  This is a function that requests an in-app purchase. For details, see [createOneTimePurchaseOrder](#createonetimepurchaseorder).
* getPendingOrderstypeof getPendingOrders

  It retrieves a list of pending orders. For details, see [getPendingOrders](#getpendingorders) Please refer to the documentation.
* getCompletedOrRefundedOrderstypeof getCompletedOrRefundedOrders

  It retrieves a list of orders purchased or refunded via in-app purchase. For details, see [getCompletedOrRefundedOrders](#getcompletedorrefundedorders) Please refer to the documentation.
* completeProductGranttypeof completeProductGrant

  It sends a message to the app saying that product grant processing is complete. For details, see [completeProductGrant](#completeproductgrant) Please refer to the documentation.

### View product list <a href="#getproductitemlist" id="getproductitemlist"></a>

**SDK function:** `getProductItemList`

`getProductItemList` is a function that contains a list of products that can be purchased with in-app purchases. It is used when displaying the product list on screen.

**Signature**

```typescript
function getProductItemList(): Promise<{ products: IapProductListItem[] } | undefined>;
```

**Return value**

* `Promise<{ products: IapProductListItem\[] } | undefined>`

  Returns an object containing the product list. If the app version is lower than the minimum supported version (5.219.0), `undefined`is returned.

**Properties**

```typescript
interface IapProductListItem {
  sku: string;
  displayAmount: string;
  displayName: string;
  iconUrl: string;
  description: string;
}
```

* IapProductListItem

  An object containing information about a single product that can be purchased via in-app purchase. It is used when displaying the product list on screen.
* **sku** · Required · `string`

  The product's unique ID. [IAP.createOneTimePurchaseOrder](#createonetimepurchaseorder)used when calling `productId`is the same value as.

**Example**

Get a list of purchasable in-app products

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

```js
import { IAP } from '@apps-in-toss/web-framework';

async function handleGetProductItemList() {
  const response = await IAP.getProductItemList();

  return response?.products ?? [];
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { IAP, IapProductListItem } from '@apps-in-toss/web-framework';
import { Button, List, ListRow } from '@toss/tds-mobile';
import { useEffect, useState, useCallback } from 'react';

function IapProductList() {
  const [products, setProducts] = useState<IapProductListItem[]>([]);

  const handleBuy = useCallback(() => {
    const cleanup = IAP.createOneTimePurchaseOrder({
      options: {
        sku,
        processProductGrant: ({ orderId }) => {
          // Write the product grant logic.
          return true; // Return whether the product was granted.
        },
      },
      onEvent: (event) => {
        console.log(event);

        if (event.type === 'success') {
          cleanup();
        }
      },
      onError: (error) => {
        console.error(error);
        cleanup();
      },
    });
  }, [sku]);

  useEffect(() => {
    async function fetchProducts() {
      try {
        const response = await IAP.getProductItemList();
        setProducts(response?.products ?? []);
      } catch (error) {
        console.error('Failed to get product list:', error);
      }
    }

    fetchProducts();
  }, []);

  return (
    <List>
      {products.map((product) => (
        <ListRow
          key={product.sku}
          left={<ListRow.Image type="square" src={product.iconUrl} />}
          contents={
            <ListRow.Texts
              type="3RowTypeA"
              top={product.displayName}
              middle={product.description}
              bottom={product.displayAmount}
            />
          }
          right={
            <Button size="medium" onClick={() => handleBuy(product.sku)}>
              Buy
            </Button>
          }
        />
      ))}
    </List>
  );
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { IAP, IapProductListItem } from '@apps-in-toss/framework';
import { Button, List, ListRow } from '@toss/tds-react-native';
import { useEffect, useState, useCallback } from 'react';

function IapProductList() {
  const [products, setProducts] = useState<IapProductListItem[]>([]);

  const handleBuy = useCallback(() => {
    const cleanup = IAP.createOneTimePurchaseOrder({
      options: {
        sku,
        processProductGrant: ({ orderId }) => {
          // Write the product grant logic.
          return true; // Return whether the product was granted.
        },
      },
      onEvent: (event) => {
        console.log(event);

        if (event.type === 'success') {
          cleanup();
        }
      },
      onError: (error) => {
        console.error(error);
        cleanup();
      },
    });
  }, [sku]);

  useEffect(() => {
    async function fetchProducts() {
      try {
        const response = await IAP.getProductItemList();
        setProducts(response?.products ?? []);
      } catch (error) {
        console.error('Failed to get product list:', error);
      }
    }

    fetchProducts();
  }, []);

  return (
    <List>
      {products.map((product) => (
        <ListRow
          key={product.sku}
          left={<ListRow.Image type="square" source={{ uri: product.iconUrl }} />}
          right={
            <Button size="medium" onPress={() => handleBuy(product.sku)}>
              Buy
            </Button>
          }
          contents={
            <ListRow.Texts
              type="3RowTypeA"
              top={product.displayName}
              middle={product.description}
              bottom={product.displayAmount}
            />
          }
        />
      ))}
    </List>
  );
}
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
  "products": [
    {
      "sku": "sku1",
      "displayName": "Remove ads",
      "displayAmount": "₩4,900",
      "iconUrl": "https://cdn.example.com/icons/premium-monthly.png",
      "description": "Remove ads and provide premium features"
    },
    {
      "sku": "sku2",
      "displayName": "100 coins",
      "displayAmount": "₩9,900",
      "iconUrl": "https://cdn.example.com/icons/coin-100.png",
      "description": "100 coins usable within the app"
    }
  ]
}
```

**Try the example app**

[apps-in-toss-examples](https://github.com/toss/apps-in-toss-examples) from the repository [with-in-app-purchase](https://github.com/toss/apps-in-toss-examples/tree/main/with-in-app-purchase) Download the code and try it out.

### Request a one-time payment <a href="#createonetimepurchaseorder" id="createonetimepurchaseorder"></a>

**SDK function:** `createOneTimePurchaseOrder`

`createOneTimePurchaseOrder` This function opens the in-app purchase payment screen and lets the user complete the payment. If an error occurs during payment, it moves to an error page depending on the error type.

{% hint style="info" %}
**Note**

Within 30 seconds after payment success, `processProductGrant` if the callback is not called or the result of that callback is not true, `{appName} has a problem. Please request a refund` the page may be displayed.
{% endhint %}

**Signature**

```typescript
function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): () => void;
```

**Parameters**

```typescript
interface IapCreateOneTimePurchaseOrderOptions {
  options: { sku: string; processProductGrant: (params: { orderId: string }) => boolean | Promise<boolean> };
  onEvent: (event: SuccessEvent) => void | Promise<void>;
  onError: (error: unknown) => void | Promise<void>;
}

interface IapCreateOneTimePurchaseOrderResult {
  orderId: string;
  displayName: string;
  displayAmount: string;
  amount: number;
  currency: string;
  fraction: number;
  miniAppIconUrl: string | null;
}

interface SuccessEvent {
  type: 'success';
  data: IapCreateOneTimePurchaseOrderResult;
}
```

* **options** · Required

  Options required for in-app purchases.

  * **params.sku** · Required · `string`

    The ID of the product to order.
  * **params.processProductGrant** · Required · `(params: { orderId: string }) => boolean | Promise<boolean>`

    Called when actually granting the product after the order is created. `orderId`and returns whether the grant was successful. `true` or `Promise<true>`If the grant fails, `false`is returned.
* **onEvent** · Required · `(event: SuccessEvent) => void | Promise<void>`

  Called when payment succeeds.

  * **event.type** · Required · `"success"`

    is the type of the event. `"success"`is returned.
  * **event.data** · Required · `IapCreateOneTimePurchaseOrderResult`

    When the in-app purchase is complete, it returns the payment details and product information. You can use the returned information to display the purchased product's information on screen.

    * **event.data.orderId** · Required · `string`

      The payment order ID. After payment is complete, [check the payment status](https://developers-apps-in-toss.toss.im/api/getIapOrderStatus.html)to use.
    * **event.data.displayName** · Required · `string`

      The product name to display on screen.
    * **event.data.displayAmount** · Required · `string`

      Price information including the currency unit.
    * **event.data.amount** · Required · `number`

      The numeric value of the product price.
    * **event.data.currency** · Required · `string`

      The currency unit of the product price.
    * **event.data.fraction** · Required · `number`

      A value that determines how many digits after the decimal point to show when displaying the price.
    * **event.data.miniAppIconUrl** · `string | null`

      The URL of the mini app icon image.
* **onError** · Required · `(error: unknown) => void | Promise<void>`

  Called when an error occurs during payment. You can receive the error object and log it or run recovery steps.

**Error code**

* INVALID\_PRODUCT\_ID : The product ID is invalid, or the product does not exist. Please check the product ID.

  Occurs when the product ID is invalid or the product does not exist.

**Return value**

* () => void

  Returns the app bridge cleanup function. After the in-app purchase feature is finished, you must call this function to release resources.

**Example**

Navigate to a specific in-app purchase order page

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

```js
import { IAP } from '@apps-in-toss/web-framework';

let cleanup;

function handleBuyProduct(sku) {
  cleanup = IAP.createOneTimePurchaseOrder({
    options: {
      sku,
      processProductGrant: ({ orderId }) => {
        console.log('Product grant logic executed:', orderId);
        return true;
      },
    },
    onEvent: (event) => {
      console.log('Event:', event);
      cleanup?.();
    },
    onError: (error) => {
      console.error('In-app purchase failed:', error);
      cleanup?.();
    },
  });
}

window.addEventListener('pagehide', () => {
  cleanup?.();
});
```

{% endtab %}

{% tab title="React" %}

```tsx
import { IAP } from '@apps-in-toss/web-framework';
import { Button } from '@toss/tds-mobile';
import { useCallback } from 'react';

interface Props {
  sku: string;
}

function IapCreateOneTimePurchaseOrderButton({ sku }: Props) {
  const handleBuy = useCallback(() => {
    const cleanup = IAP.createOneTimePurchaseOrder({
      options: {
        sku,
        processProductGrant: ({ orderId }) => {
          // Write the product grant logic.
          return true; // Return whether the product was granted.
        },
      },
      onEvent: (event) => {
        console.log(event);
        cleanup();
      },
      onError: (error) => {
        console.error(error);
        cleanup();
      },
    });
  }, [sku]);

  return <Button onClick={handleBuy}>Buy</Button>;
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { IAP } from '@apps-in-toss/framework';
import { Button } from '@toss/tds-react-native';
import { useCallback } from 'react';

interface Props {
  sku: string;
}

function IapCreateOneTimePurchaseOrderButton({ sku }: Props) {
  const handleClick = useCallback(() => {
    const cleanup = IAP.createOneTimePurchaseOrder({
      options: {
        sku,
        processProductGrant: ({ orderId }) => {
          // Write the product grant logic.
          return true; // Return whether the product was granted.
        },
      },
      onEvent: (event) => {
        console.log(event);
        cleanup();
      },
      onError: (error) => {
        console.error(error);
        cleanup();
      },
    });
  }, []);

  return <Button onPress={handleClick}>Buy</Button>;
}
```

{% endtab %}
{% endtabs %}

**Try the example app**

[apps-in-toss-examples](https://github.com/toss/apps-in-toss-examples) from the repository [with-in-app-purchase](https://github.com/toss/apps-in-toss-examples/tree/main/with-in-app-purchase) Download the code and try it out.

### Check pending orders <a href="#getpendingorders" id="getpendingorders"></a>

**SDK function:** `getPendingOrders`

`getPendingOrders` is **A list of orders whose payment is complete but whose products have not yet been granted**This function retrieves them. Check the retrieved order information and grant the product to the user. `createOneTimePurchaseOrder` Even if you do not receive a result after calling the function, you can still query that order.

If the app version is lower than the minimum supported version (Android 5.234.0, iOS 5.231.0), `undefined`is returned.

**Signature**

```typescript
function getPendingOrders(): Promise<{ orders: Order[] } | undefined>;
```

**Return value**

* `Promise<{ orders: Order[] } | undefined>`

  Returns an object containing the list of pending orders (orders). If the app version is lower than the minimum supported version (Android 5.234.0, iOS 5.231.0), `undefined`is returned.

**Returned object properties**

```tsx
interface Order {
  orderId: string;
  sku: string;
  paymentCompletedDate?: string;
}
```

* **orders** · Required · `Order[]`

  An array of pending orders. If there are no pending orders, it returns an empty array.
* **orders\[].orderId** · Required · `string`

  The order's unique ID.
* **orders\[].sku** · Required · `string`

  The order product's unique ID.
* **orders\[].paymentCompletedDate** · Required · `string`

  Indicates when payment was completed.

{% hint style="info" %}
**Field update notice**

* **SDK 1.4.2**: `sku` The field has been added. This field is returned only on **Android 5.234.0 or later, iOS 5.231.0 or later**.
* **SDK 1.4.8**: `paymentCompletedDate` The field has been added. You can check the payment completion time.
  {% endhint %}

**Example**

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

```js
import { IAP } from '@apps-in-toss/web-framework';

async function fetchOrders() {
  try {
    const pendingOrders = await IAP.getPendingOrders();
    return pendingOrders;
  } catch (error) {
    console.error(error);
  }
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { IAP } from '@apps-in-toss/web-framework';

async function fetchOrders() {
  try {
    const pendingOrders = await IAP.getPendingOrders();
    return pendingOrders;
  } catch (error) {
    console.error(error);
  }
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { IAP } from '@apps-in-toss/framework';

async function fetchOrders() {
  try {
    const pendingOrders = await IAP.getPendingOrders();
    return pendingOrders;
  } catch (error) {
    console.error(error);
  }
}
```

{% endtab %}
{% endtabs %}

### Complete product grant processing <a href="#completeproductgrant" id="completeproductgrant"></a>

**SDK function:** `completeProductGrant`

`completeProductGrant` The function **is a function that completes product grant for pending orders**It grants the product to the user and `completeProductGrant` call the function to change the grant status to complete.

If the app version is lower than the minimum supported version (Android 5.231.0, iOS 5.231.0), `undefined`is returned.

**Signature**

```typescript
function completeProductGrant(params: {
  params: {
    orderId: string;
  };
}): Promise<boolean | undefined>;
```

**Parameters**

* { params: { orderId: string } }

  An object containing order information for which payment has been completed.

  * **params.order** · `Id string`

    The order's unique ID. Used when specifying the order for which product granting should be completed.

**Return value**

* `Promise<boolean | undefined>`

  Returns whether product grant is complete. If the app version is lower than the minimum supported version (Android 5.233.0, iOS 5.233.0), `undefined`is returned.

**Example**

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

```js
import { IAP } from '@apps-in-toss/web-framework';

async function handleCompleteProductGrant(orderId) {
  try {
    await IAP.completeProductGrant({ params: { orderId } });
  } catch (error) {
    console.error(error);
  }
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { IAP } from '@apps-in-toss/web-framework';

async function handleCompleteProductGrant(orderId: string) {
  try {
    await IAP.completeProductGrant({ params: { orderId } });
  } catch (error) {
    console.error(error);
  }
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { IAP } from '@apps-in-toss/framework';

async function handleCompleteProductGrant(orderId: string) {
  try {
    await IAP.completeProductGrant({ params: { orderId } });
  } catch (error) {
    console.error(error);
  }
}
```

{% endtab %}
{% endtabs %}

### View completed/refunded orders <a href="#getcompletedorrefundedorders" id="getcompletedorrefundedorders"></a>

**SDK function:** `getCompletedOrRefundedOrders`

`getCompletedOrRefundedOrders` It retrieves a list of orders purchased via in-app purchase and refunded. You can query orders for which in-app purchase payment and product grant have been completed, and refunded orders.

Orders whose payment is complete but whose products have not yet been granted are not queried. [`getPendingOrders`](#getpendingorders)Through the function `orderId`query [`completeProductGrant`](#completeproductgrant)to grant the product to the user, then

If the app version is lower than the minimum supported version (Android 5.231.0, iOS 5.231.0), `undefined`is returned.

{% hint style="info" %}
**Pagination**

* **Up to 50 per page** orders are returned.
* When there is a next page, `hasNext`is `true`, and the response's `nextKey`pass it as the next call's `key` parameter to continue querying.
  {% endhint %}

**Signature**

```typescript
function getCompletedOrRefundedOrders(params?: {
  key?: string | null;
}): Promise<CompletedOrRefundedOrdersResult | undefined>;
```

**Return value**

* `Promise<{ CompletedOrRefundedOrdersResult } | undefined>`

  Returns an object containing the order list, including pagination. If the app version is lower than the minimum supported version (Android 5.231.0, iOS 5.231.0), `undefined`is returned.

**Returned object properties**

```tsx
interface CompletedOrRefundedOrdersResult {
  hasNext: boolean;
  nextKey?: string | null;
  orders: {
    orderId: string;
    sku: string;
    status: 'COMPLETED' | 'REFUNDED';
    date: string;
  }[];
}
```

* **hasNext** · Required · `boolean`

  Indicates whether there is a next page. `` `true` ``If so, there are more orders remaining.
* **nextKey optional** · `string | null · null`

  This is the cursor key for querying the next page. Use the value from the previous response. `nextKey` For the first call, omit it or `null`pass it as.
* **orders** · Required · `Array`

  An array containing order information. Each element represents one order.
* **orders\[].orderId** · Required · `string`

  The order's unique ID.
* **Example**
*
*
* ### Order status lookup API
* You can directly query in-app purchase order status from the server through the API. You can also use it even if you did not receive an approval or refund response.
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Note</strong></p><p>To use the payment status inquiry API, please first set up Toss login integration.</p></div>
* Content-type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/order/get-order-status`
* **Request headers**
* If you do not include the header, all orders will be returned.
* In the header, `x-toss-user-key` If you include the value, only orders for that userKey will be returned.
* **Request parameters**
* ```json
  {
    "orderId": "13c9a1ff-2baa-4495-bbfa-a0826ba8c7c0"
  }
  ```
* **Response**
* **status (enum)**
* **Response example**
* ```json
  {
    "resultType": "SUCCESS",
    "success": {
      "orderId": "13c9a1ff-2baa-4495-bbfa-a0826ba8c7c0",
      "sku": "ait.0000010000.af647449.3bd55cfd00.0000000475",
      "statusDeterminedAt": "2025-09-12T16:57:12",
      "status": "PAYMENT_COMPLETED",
      "reason": "The payment has been completed."
    }
  }
  ```
* ```json
  {
    "resultType": "SUCCESS",
    "success": {
      "orderId": "13c9a1ff-2baa-4495-bbfa-0000000000",
      "sku": "ait.0000010000.af647449.00000000000.0000000475",
      "statusDeterminedAt": "2025-09-12T16:57:12",
      "status": "PURCHASED",
      "reason": "This is a completed order."
    }
  }
  ```
*
* ### Sandbox test
* Before release, be sure to **sandbox app environment**test whether in-app purchases work properly. In the sandbox, no actual payment (billing) occurs, and all payments are handled as test scenarios.
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Note</strong></p><p>Current sandbox testing only supports <strong>one-time payments</strong>. Sandbox testing for subscription payments is not currently supported.</p></div>
* **1. Behavior when querying the product list in the sandbox**
* In the sandbox app, `getProductItemList()`when called, among the in-app purchase products registered in the console, only those with **display status ON**are retrieved.
* The product list registered in the actual console is returned as-is.
* In the console, **products with display OFF**will not appear in the sandbox app either.
* **2. Required test scenarios**
* In the sandbox, you must perform the following three tests separately. Please verify that the app responds correctly in each scenario.
* **① Payment success test**
* Make sure the success callback (`event.type: success`) is delivered properly.
* No actual payment (billing) occurs.
* In SDK 1.1.3 and later, the partner's **final success is processed only when the product delivery logic**also succeeds.
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Items to check</strong></p><ul><li><code>orderId</code>, <code>amount</code> etc. <code>event.data</code> Whether it returns normally</li><li>Whether the internal delivery logic works properly</li><li>Screen/UI update after delivery is complete</li></ul></div>
* \[Watch video]\(../../../../resources/development/iap/iap\_sandbox\_test\_1.mp4)
* **② Payment success (server failure) test**
* You must test the case where payment succeeds but the partner server's delivery logic fails.
* The app should support the following handling:
* After delivery is complete `completeProductGrant` call
* when the app is restarted `getPendingOrders`restore pending orders with
* notify the user of delivery failure
* This is a scenario that can happen often in real service, so be sure to test it.
* \[Watch video]\(../../../../resources/development/iap/iap\_sandbox\_test\_2.mp4)
* **③ Error test**
* Pre-simulate various situations in which errors occur during payment.
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Representative situations to test</strong></p><ul><li>Network error</li><li>User cancels payment</li><li>Internal error</li><li>Partner product delivery failure</li></ul></div>
* \[Watch video]\(../../../../resources/development/iap/iap\_sandbox\_test\_3.mp4)
* **3. Test checklist**
*
* ### Frequently asked questions
*
*
*
*

| Test item                                                     | Required    | Check point                                                          |
| ------------------------------------------------------------- | ----------- | -------------------------------------------------------------------- |
| Product list display                                          | ✔️          | Whether the products registered in the console are returned properly |
| Payment success test                                          | ✔️          | `event.data` processing, delivery logic, UI handling                 |
| Payment success + server delivery failure (order restoration) | ✔️          | Restore pending orders and handle redelivery                         |
| Error test                                                    | ✔️          | Error UI, error handling, retry flow                                 |
| Order status lookup API                                       | Recommended | Server validation and consistency check                              |

| Status              | Description       | Detailed description                                                                   |
| ------------------- | ----------------- | -------------------------------------------------------------------------------------- |
| PURCHASED           | Order completed   | The in-app payment and product delivery have both been completed                       |
| PAYMENT\_COMPLETED  | Payment completed | In SDK 1.1.3 and later, the payment has been completed but product delivery failed     |
| FAILED              | Order failed      | When payment fails                                                                     |
| REFUNDED            | Order refunded    | When the refund has been completed                                                     |
| ORDER\_IN\_PROGRESS | Order in progress | When the order has been created but payment/delivery processing has not been completed |
| NOT\_FOUND          | Order not found   | When the order number cannot be found                                                  |
| MINIAPP\_MISMATCH   | Product mismatch  | When the ordered product is not a product of the corresponding app                     |
| ERROR               | Internal error    | When an internal system error occurs                                                   |

| Name               | Type   | Description                                                                                                                            |
| ------------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| orderId            | String | Requested order number                                                                                                                 |
| sku                | String | Ordered product ID                                                                                                                     |
| statusDeterminedAt | String | Order completion date and time (yyyy-MM-dd'T'HH:flag\_mm:ss, fixed to KST) `status`is `REFUNDED`If so, refund completion date and time |
| status             | String | Status for the order (enum)                                                                                                            |
| reason             | String | Description of the status                                                                                                              |

| Name    | Type   | Required | Description                                                |
| ------- | ------ | -------- | ---------------------------------------------------------- |
| orderId | String | Y        | Order number (uuid v7) obtained after creating the payment |

| Name            | Type   | Required value 여부 | Description                               |
| --------------- | ------ | ----------------- | ----------------------------------------- |
| x-toss-user-key | string | N                 | userKey value obtained through Toss login |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/common/monetization/iap/in-app-purchase.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
