> This is part 1 of 2 of the full documentation (pages 1–100 of 133).
> The content is paginated: fetch every part to see all of it.
> Next part: https://docs.tebex.io/developers/llms-full.txt/1
> Page index: https://docs.tebex.io/developers/llms.txt

# Welcome

Learn how to integrate Tebex and leave the complexities of monetization to us.

Welcome to the Tebex developer documentation. If you're new, start with our [quick start guide](/developers/getting-started) or explore one of our products below. If you need assistance during the integration process, don’t hesitate to [reach out](https://www.tebex.io/support-creator) - we’re here to help.&#x20;

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Webstore Builder</strong></td><td>Create custom store designs that perfectly align with your brand identity.</td><td></td><td><a href="/developers/templates/overview">Webstore Builder</a></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FoTW8mn2mI7UbszJk5rad%2FDocument%20Text.png?alt=media&amp;token=a3246235-5aa9-49db-ad51-9e50c343834a">Document Text.png</a></td></tr><tr><td><strong>Headless API</strong></td><td>Seamlessly integrate Tebex into your own website or directly within your game.</td><td></td><td><a href="/developers/headless-api/introduction">Headless API</a></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2F2QQPfXx1i55fn0YLELal%2FBow.png?alt=media&amp;token=93f97c3a-34f1-4c1c-9cd7-dfbca0232e49">Bow.png</a></td></tr><tr><td><strong>Checkout API</strong></td><td>Create sophisticated and customized checkout experiences.</td><td></td><td><a href="/developers/checkout-api/overview">Checkout API</a></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FPlPi3fuAn8P2pPzoR2wG%2FCrystals.png?alt=media&amp;token=f24eaa5c-82b5-461e-b550-4025b0ae83b5">Crystals.png</a></td></tr><tr><td><strong>Tebex.js</strong></td><td>A checkout experience that aligns with your brand, all without leaving your website.</td><td></td><td><a href="/developers/tebex.js/overview">Tebex.js</a></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FlVfDxMyMU1BcxBxLaw6V%2FDocuments.png?alt=media&amp;token=3ff27e5e-0f69-4222-b4ac-cbcf905b35c8">Documents.png</a></td></tr><tr><td><strong>Webhooks</strong></td><td>Receive real-time notifications of payments to facilitate automatic product delivery.</td><td></td><td><a href="/developers/webhooks/overview">Webhooks</a></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2Fn7sBFDDT0cY0vUPT9OGL%2FSwords.png?alt=media&amp;token=ed2fce6f-5ed0-456f-8868-b2dace5a2681">Swords.png</a></td></tr><tr><td><strong>Game Server API</strong></td><td>Integrate automatic product delivery into your game server using our API or official plugins.</td><td></td><td><a href="/developers/game-server-api/overview">Game Server API</a></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxfdgB9WDLarwPZlahwsg%2FTreasure%20Chest%201.png?alt=media&amp;token=6cabd1d1-77f1-45c8-b213-535ae359c93b">Treasure Chest 1.png</a></td></tr></tbody></table>


# Getting Started

Get started integrating Tebex into your website or game

Welcome to your journey of launching your first project with Tebex! This guide will walk you through the essential steps to create, set up, and launch your store, ensuring a seamless experience for your customers. From building your first project in the creator panel to implementing automatic product delivery, we'll cover everything you need to know to get started.

{% stepper %}
{% step %}

### Create a project

Head over to the [creator panel](https://creator.tebex.io) and kick things off by creating your first project.
{% endstep %}

{% step %}

### Setup your store or integrate our APIs

Check out the docs for the [integration method](/developers/integration-methods) you’re going with. If needed, build the APIs into your website or game.&#x20;
{% endstep %}

{% step %}

### Create your packages

If your integration method requires it, [create the packages](https://creator.tebex.io/packages) your customers can buy.
{% endstep %}

{% step %}

### Implement product delivery

Make sure your customers get their packages right away after they’ve made a purchase. For game studios, [webhooks](/developers/webhooks/overview) or license keys (like Steam keys) are the way to go. If you’re monetizing a game server, don’t forget to check out our [official plugins](/developers/game-server-api/overview) for that.
{% endstep %}

{% step %}

### Make a test payment

Before going live, give everything a test run by going through the checkout process using the test payment method. Don’t worry, no real money needed here!
{% endstep %}

{% step %}

### Submit for review

Ready to roll? Submit your project for review by our Content & Safety team. We’ll give it a quick check, and if everything looks good, you’ll be ready to launch within a day.
{% endstep %}

{% step %}

### Go live

Once you’re approved, you’re all set to go live and start making money from your game! Plus, with us as your Merchant of Record, you’ll get access to worldwide payment methods, tax handling, and fraud protection. Nice! :sunglasses::tada:
{% endstep %}
{% endstepper %}


# Integration Methods

Learn which integration method is best for you

Tebex offers multiple integration options tailored to meet different business needs, each equipped with unique features for specific use cases.

There are three integration methods available, as highlighted below. Each method varies in complexity, with the Webstore Builder being the easiest to get started with.

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden></th><th data-hidden data-type="checkbox"></th></tr></thead><tbody><tr><td><strong>Webstore Builder</strong><br><em><mark style="color:purple;">Easiest</mark></em><br></td><td><p>✅  <mark style="color:green;">Checkout</mark></p><p><mark style="color:green;">✅  Package Management</mark></p><p><mark style="color:green;">✅  Hosted Webstore</mark><br><br><a href="/developers/templates/overview">Webstore Builder Docs</a></p></td><td></td><td><a href="/developers/templates/overview">Webstore Builder</a></td><td></td><td>false</td></tr><tr><td><strong>Headless API</strong><br><em><mark style="color:orange;">Complex</mark></em><br></td><td><p>✅  <mark style="color:green;">Checkout</mark></p><p><mark style="color:green;">✅  Package Management</mark></p><p><del>*  Hosted Webstore</del><br><br><a href="/developers/headless-api/introduction">Headless API Doc</a><a href="/developers/headless-api/introduction">s</a></p></td><td></td><td><a href="/developers/headless-api/introduction">Headless API</a></td><td></td><td>false</td></tr><tr><td><strong>Checkout API</strong><br><em><mark style="color:red;">Advanced</mark></em><br></td><td><p>✅  <mark style="color:green;">Checkout</mark></p><p><del>*  Package Management</del></p><p><del>*  Hosted Webstore</del><br><br><a href="/developers/checkout-api/overview">Checkout API Docs</a></p></td><td></td><td><a href="/developers/checkout-api/overview">Checkout API</a></td><td></td><td>false</td></tr></tbody></table>

**Checkout**: Maximize revenue by utilizing Tebex’s global Merchant of Record platform. With over 100 payment methods, Tebex handles the entire checkout process, offering chargeback protection, fraud monitoring, 14-day payouts, and international sales tax coverage.

**Package Management**: Effortlessly set up and manage packages for sale on your project through the creator panel. You can organize packages into categories and easily define details such as names, descriptions, pricing, and images. You're also able to invite other team members to manage these too.

**Hosted Webstore**: Tebex provides a customizable webstore that allows you to start selling in minutes. This enables you to focus on your business, while we handle the hosting infrastructure & technical requirements for you.

### Which integration method is best for me?

Take a look at the example scenarios below to get a better understanding of which integration method is best for you. Whatever you choose, all of our integration methods come with access to over 100 payment methods, international sales tax coverage, fraud protection, [webhooks](/developers/webhooks/overview), and seamless inline checkout through [Tebex.js](/developers/tebex.js/overview).

<details>

<summary>I want to sell packages via a pre-built webstore that's hosted for me</summary>

If you're looking for a pre-built, hosted webstore, we recommend using the Tebex [Webstore Builder](/developers/templates/overview). This tool offers comprehensive package management through the Tebex creator panel, a fully customizable webstore displaying all your available packages, and a built-in add-to-cart feature. Webstores are seamlessly integrated with [Tebex.js](/developers/tebex.js/overview), our inline checkout solution. To see an example of a webstore created with the Webstore Builder, visit [example.tebex.io](https://example.tebex.io).

</details>

<details>

<summary>I want to sell packages from my own website or in-game</summary>

If you want to sell packages directly through your own website or in-game, while managing package creation, updates, and configuration via Tebex, the [Headless API](/developers/headless-api/introduction) is the ideal solution. By integrating the Headless API with [Tebex.js](/developers/tebex.js/overview), you can offer a seamless checkout experience, allowing customers to make purchases without leaving your site.

</details>

<details>

<summary>I want to sell packages that are dynamic in nature</summary>

If your packages require a high level of customization for each customer and cannot be created within the Tebex creator panel, the Checkout API is the ideal solution. For example, this could apply to packages with varying names, descriptions, pricing, or images tailored to individual customers. By integrating the Checkout API with [Tebex.js](/developers/tebex.js/overview), you can provide a smooth purchasing experience, allowing customers to complete transactions without leaving your website.

</details>

<details>

<summary>I want to sell hundreds or thousands of packages through my own backend system</summary>

If you manage a large volume of packages that would be impractical to create manually in the Tebex creator panel, or if your package offerings update based on your internal inventory system, the [Checkout API](/developers/checkout-api/overview) is the optimal solution. By integrating the Checkout API with [Tebex.js](/developers/tebex.js/overview), you can offer a seamless purchasing experience, allowing customers to complete transactions without leaving your website.

</details>

<details>

<summary>I want to sell physical goods or launch a marketplace</summary>

Tebex cannot support projects that aim to sell physical goods or provide marketplace services. If you are looking to pursue either of these options, we regret to inform you that we cannot collaborate in this capacity, and you will need to seek a payment partner elsewhere.

</details>

### Let's begin!

Now that you've chosen your integration method, you can begin by exploring the relevant documentation:

* Learn how to design your own store using the [**Webstore Builder**](/developers/templates/overview).
* Sell packages directly from your website or in-game with the [**Headless API**](/developers/headless-api/introduction).
* For more complex integrations, get started with the [**Checkout API**](/developers/checkout-api/overview).


# Overwolf Apps

How to use Tebex with Overwolf Apps

The Overwolf Subscriptions API enables developers to seamlessly integrate subscription-based monetization into their Overwolf apps using a Tebex Store. This integration provides a complete subscription management system - removing the need to handle payment processing, track subscription statuses, or build complex server-side infrastructure.

#### Get Started with Overwolf App Monetization

Before implementing subscriptions, review Overwolf’s documentation to understand the available monetization options and how to incorporate them into your app.

**Learn more:** [Overwolf App Monetization Guide](https://dev.overwolf.com/ow-native/monetization/implementation/)

This guide covers:

* Supported monetization models in Overwolf
* How Tebex integrates into the Overwolf ecosystem
* Steps for setting up and linking your Tebex Store

#### Explore the Overwolf Subscriptions API Reference

The Overwolf Subscriptions API provides all the endpoints and methods you’ll need to manage your users’ subscriptions through Tebex. It includes details on authentication, subscription lifecycle management, and user entitlement verification.

**View the full API documentation:** [Overwolf Subscriptions API Reference](https://dev.overwolf.com/ow-native/reference/subscriptions-api)

Use this reference to:

* Fetch active subscriptions for users
* Verify subscription status within your app
* Manage user access based on entitlement data

#### Review the Example App

To see a working implementation, Overwolf provides an example application demonstrating how to use the Tebex Subscriptions API in a sample application.

**Explore the sample app on GitHub:** [Tebex Subscriptions Example App](https://github.com/overwolf/tebex-subs-sample)

This repository includes:

* End-to-end integration examples
* Code samples for handling subscription data
* Reference architecture for production deployments


# SDKs

Tebex offers many different ways to integrate with your existing infrastructure.

## Official SDKs

The SDKs below include support for **Headless API**, **Checkout API**, and **Webhooks**, complete with examples, making implementation of these APIs into your project as easy as possible.

<table><thead><tr><th width="139">Language</th><th width="187">Package Manager</th><th>Link</th></tr></thead><tbody><tr><td>PHP</td><td>Composer / Packagist</td><td><a href="https://packagist.org/packages/tebex/tebex-sdk-php">https://packagist.org/packages/tebex/tebex-sdk-php</a></td></tr><tr><td>NodeJS</td><td>NPM</td><td><a href="https://www.npmjs.com/package/@tebexio/tebex-sdk-nodejs">https://www.npmjs.com/package/@tebexio/tebex-sdk-nodejs</a></td></tr><tr><td>C#</td><td>N/A</td><td><a href="https://github.com/tebexio/Tebex-CSharp">https://github.com/tebexio/Tebex-CSharp</a></td></tr></tbody></table>

## OpenAPI Schema

Tebex APIs are documented using OpenAPI. These are used to generate our **Endpoints** documentation. Our schemas are available at the GitHub repositories below. The OpenAPI Generator can be used to generate an SDK in the language of your choice if we do not have your language available.

<table><thead><tr><th width="188">API</th><th>Repository Link</th></tr></thead><tbody><tr><td>Headless API</td><td><a href="https://github.com/tebexio/TebexHeadless-OpenAPI">https://github.com/tebexio/TebexHeadless-OpenAPI</a></td></tr><tr><td>Checkout API</td><td><a href="https://github.com/tebexio/TebexCheckout-OpenAPI/">https://github.com/tebexio/TebexCheckout-OpenAPI</a></td></tr></tbody></table>

## Other SDKs / Integration Options

Below are additional resources and projects that can help you implement Tebex into your project. If you've developed an SDK, please reach out to us at **<tebex-integrations@overwolf.com>**.

<table><thead><tr><th>Language</th><th width="347">GitHub Repository</th><th>Support</th></tr></thead><tbody><tr><td>Nuxt.js</td><td><a href="https://github.com/tebexio/Headless-Template">tebexio/Headless-Template</a></td><td>Official</td></tr><tr><td>Typescript</td><td><a href="https://github.com/Tynopia/tebex_headless">Tynopia/tebex_headless</a></td><td>Third Party</td></tr><tr><td>PHP</td><td><a href="https://github.com/Nabla-Corporation/tebex_headless_php">Nabla-Corporation/tebex_headless_php</a></td><td>Third Party</td></tr></tbody></table>


# Tebex for Unreal Engine 5

If you're developing a game for UE5, Tebex makes monetization simple.

We've built an open-source SDK for Unreal Engine 5 that provides everything needed to quickly start integrating with Tebex:

* C++ mappings for **Headless API**&#x20;
* C++ mappings for the **Plugin API**
* An example in-game **Plugin**

**GitHub Repository:** [tebexio/Tebex-UE5](https://github.com/tebexio/Tebex-UE5)

When you're ready to start processing payments for your Unreal game, we’d love to connect. [Reach out to us](https://www.tebex.io/contact-sales) to get started.


# Tebex for Unity Engine

Tebex is the easiest platform for adding payments to your Unity game.

<figure><img src="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FupKtzQfABPMPPIUlohaD%2Fimage.png?alt=media&amp;token=e5c106b7-c8bc-45aa-b6f8-8252f236a0d9" alt=""><figcaption></figcaption></figure>

We provide a dedicated Unity SDK and demo project that provides all tooling necessary for you to add a fully interactive Tebex store and cart into your game.

<p align="center"><a href="https://buycraft-plugins.s3.us-west-1.amazonaws.com/latest/unity-demo/index.html" class="button primary">Open Tebex Demo</a></p>

**Features**

* Store Browser
* In-Game Cart
* Link out checkout
* QR code checkout

**Github Repository:** <https://github.com/tebexio/Tebex-Unity>

For further details, see our [Getting Started](/developers/unity-engine/getting-started) guide for Unity Engine.

When you're ready to start processing payments for your Unity game, we’d love to connect. [Reach out to us](https://www.tebex.io/contact-sales) to get started.


# Overview

Customise your store to match your games brand using our Webstore Builder.

The Webstore Builder enables you to fully customise the design of your store using templates & themes, providing your customers with a seamless transition from your existing website when they're making a purchase.

If you haven't already done so, we recommend having a read of our [quick start guide](/developers/getting-started) before continuing.

With the webstore builder, you can:

1. Use templates to change the HTML structure of each page and implement conditional logic via the [TWIG templating engine](/developers/templates/twig).
2. Upload custom CSS, Javascript and images via [Assets](/developers/templates/assets).
3. If you're a template designer, you can offer your customers the ability to customise their templates via [Config Schema](/developers/templates/schema), and you're also eligible for free Plus via our [Developer Plan](/developers/templates/developer-plan).

## Examples

Browse examples of other Tebex stores for some inspiration.&#x20;

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><p></p><p><strong>Example Store</strong></p></td><td><a href="https://example.tebex.io">https://example.tebex.io</a></td><td></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FTWjybl7uZyz5Ebnonrxv%2F1%201.png?alt=media&amp;token=93939ff5-b713-41a9-9979-73e8cd6ae5ac">1 1.png</a></td><td><a href="https://example.tebex.io">https://example.tebex.io</a></td></tr><tr><td><p></p><p><strong>Hypixel</strong></p></td><td><a href="https://store.hypixel.net">https://store.hypixel.net</a></td><td></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2F6CwcbP0UYmXowRWXkU3d%2Fimage%202.png?alt=media&amp;token=e97e9a84-41c9-455e-8af2-b594ca71916c">image 2.png</a></td><td><a href="https://store.hypixel.net">https://store.hypixel.net</a></td></tr></tbody></table>

## Certified Tebex Designers

If you're a designer who creates templates for others, either for free or to sell, [let us know](https://forms.monday.com/forms/fce1c5555703d90861656cd5571d5543?r=use1)! We'll add you to the certified Tebex designers club. You'll gain access to insider help guides, a private community of other designers, feedback sessions with the Tebex product team, and also BETA features that are not yet available to others.

## Feedback

If there are any functions, tags, filters or variables that you need to use in your template, but they're not available or documented, [please let us know](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1).

## Getting Started

To create your first template, head over to the Appearance section within your [creator panel](https://creator.tebex.io).


# Getting Started

The best way to understand the functionality of the Tebex templating engine is to create a copy of our default template, named Exo.&#x20;

You can do this by navigating to **Webstore** -> **Appearance** in your control panel and creating a custom template based on Exo.&#x20;

For a live demonstration of Exo in action, visit [example.tebex.io](http://example.tebex.io).


# Twig

Discover the power of the Twig templating engine used by Tebex.

Templates on the Tebex platform are written in the [Twig Templating Engine](https://twig.symfony.com/). Twig allows you to customise your store with control structures, similar to any other language, while maintaining a sandboxed and safe environment for the Tebex infrastructure.&#x20;

You're able to learn more information about the syntax of Twig by viewing the [official documentation](https://twig.symfony.com/doc/2.x/templates.html).

A common Twig file may look like the following:

```twig
<!DOCTYPE html>
<html>
    <head>
        <title>My Webpage</title>
    </head>
    <body>
        <ul id="navigation">
        {% for item in navigation %}
            <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
        {% endfor %}
        </ul>

        <h1>My Webpage</h1>
        {{ a_variable }}
    </body>
</html>
```

{% hint style="info" %}
If you're interested in becoming a pro at the Twig syntax, you can complete the official [Twig certification programme](https://certification.symfony.com/exams/twig.html).&#x20;
{% endhint %}


# Tags

The available control structures within Twig.

Tags are control structures within Twig. They allow you to change the flow of code within your template.

If you'd like access to a TWIG tag that is not available below, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)

### Available Tags

| Tag       | Documentation                                              |
| --------- | ---------------------------------------------------------- |
| `if`      | [View](https://twig.symfony.com/doc/1.x/tags/if.html)      |
| `for`     | [View](https://twig.symfony.com/doc/1.x/tags/for.html)     |
| `block`   | [View](https://twig.symfony.com/doc/1.x/tags/block.html)   |
| `extends` | [View](https://twig.symfony.com/doc/1.x/tags/extends.html) |
| `include` | [View](https://twig.symfony.com/doc/1.x/tags/include.html) |
| `set`     | [View](https://twig.symfony.com/doc/1.x/tags/set.html)     |


# Filters

Modify variable values with Twig filters.

Filters enable you to modify the content of variables within your template.

If you'd like access to a TWIG filter that is not available below, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)

### Available Filters

| Filter          | Documentation                                                       |
| --------------- | ------------------------------------------------------------------- |
| `escape`        | [View](https://twig.symfony.com/doc/1.x/filters/escape.html)        |
| `length`        | [View](https://twig.symfony.com/doc/1.x/filters/length.html)        |
| `raw`           | [View](https://twig.symfony.com/doc/1.x/filters/raw.html)           |
| `money`         | [View](#money)                                                      |
| `slice`         | [View](https://twig.symfony.com/doc/1.x/filters/slice.html)         |
| `number_format` | [View](https://twig.symfony.com/doc/1.x/filters/number_format.html) |
| `date`          | [View](https://twig.symfony.com/doc/1.x/filters/date.html)          |
| `nl2br`         | [View](https://twig.symfony.com/doc/1.x/filters/nl2br.html)         |
| `replace`       | [View](https://twig.symfony.com/doc/1.x/filters/replace.html)       |
| `split`         | [View](https://twig.symfony.com/doc/1.x/filters/split.html)         |
| `upper`         | [View](https://twig.symfony.com/doc/1.x/filters/upper.html)         |
| `lower`         | [View](https://twig.symfony.com/doc/1.x/filters/lower.html)         |

### Filter Documentation

### `money`

The money filter transforms a variable into a monetary format.

```twig
{% set value = 1 %}

{{ value|money }} // returns 1.00
```


# Functions

View the available functions within your Twig template.

Functions generate content for you to use within your templates.

If you'd like access to a TWIG function that is not available below, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)

### Available Functions

| Function | Documentation                                                 |
| -------- | ------------------------------------------------------------- |
| `__`     | [View](#__)                                                   |
| `_p`     | [View](#_p)                                                   |
| `config` | [View](#config)                                               |
| `asset`  | [View](#asset)                                                |
| `path`   | [View](#path)                                                 |
| `query`  | [View](#query)                                                |
| `range`  | [View](https://twig.symfony.com/doc/1.x/functions/range.html) |

### Function Documentation

### `__`

Returns the equivalent translation from within your translations settings.

```twig
{{ __('Redeem coupons / gift cards') }}

// prints "Redeems coupons / gift cards" (Or the equivalent translation if another language is selected)
```

### `_p`

Returns the plural translation from within your translation settings.

```twig
{{ _p(":count items for :amount :currency", basket.packages|length, {'count' : basket.packages|length, 'amount' : basket.price|money, 'currency' : basket.currency}) }}

// prints "5 items for $5.00 USD"
```

### `config`

Returns a config value from your [template config schema](/developers/templates/schema).&#x20;

```twig
{{ config("header-colour") }}

// prints the associated config value with the key header-colour
```

### `asset`

Returns the full url path of an asset from within your template.

```twig
{{ asset("style.css") }}

// Prints the URL of style.css, such as https://your-store.tebex.io/template-assets/style.css"
```

### `path`

Returns the full url path of the current page.

```twig
{{ path() }}

// Prints the full URL of the current page the customer is browsing on your store
```

### `query`

Returns a GET parameter from the current url.

```twig
{{ query("test" }}

// Returns the GET param of "test" if it is provided in the URL.
```


# Global Variables

Accessing global variables to help populate your template with live data.

Global variables are variables which are available across all pages of your store.

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# basket

The global basket object contains all information relevant to the customers basket, such as price & packages.

| Variables  | Type            | Description                                                                    |
| ---------- | --------------- | ------------------------------------------------------------------------------ |
| `id`       | string          | Internal ID of the basket.                                                     |
| `ident`    | string          | The identifier that can be passed to [Tebex.js](/developers/tebex.js/overview) |
| `ign`      | string          | The username of the customer.                                                  |
| `uuid`     | string          | The UUID of the customer.                                                      |
| `currency` | string          | The 3 digit currency code of the basket.                                       |
| `price`    | string          | The current price of the basket.                                               |
| `packages` | array\[package] | An array of packages in the customers basket.                                  |
| `coupons`  | array\[coupon]  | An array of coupons in the customers basket.                                   |

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# store

The global store object contains all information associated with the project itself, such as store name.

<table><thead><tr><th>Variables</th><th width="272">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>string</td><td>The name of the project.</td></tr><tr><td><code>currency</code></td><td>string</td><td>The base currency of the project.</td></tr><tr><td><code>css</code></td><td>string</td><td>The custom theme currently active on the project.</td></tr><tr><td><code>logo</code></td><td>string</td><td>The full url of the custom logo of the project.</td></tr><tr><td><code>favicon</code></td><td>string</td><td>The full url of the custom favicon of the project.</td></tr><tr><td><code>noLogin</code></td><td>Boolean</td><td>If the project requires no login (e.g. if no username system is being used).</td></tr><tr><td><code>categories</code></td><td>array[category]</td><td>An array of package categories of the project.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# page

The global page object contains variables associated with the current http request.

<table><thead><tr><th width="359">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>title</code></td><td>string</td><td>The title of the current page.</td></tr><tr><td><code>message.type</code></td><td>string</td><td>The type of toast notification to display to the customer.</td></tr><tr><td><code>message.text</code></td><td>string</td><td>The contents of a toast notificaton to display to the customer</td></tr><tr><td><code>message.display</code></td><td>boolean</td><td>If a toast notification needs to be shown to the customer (eg. a validation error has occured).</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# Pages

The entry point for each page on your store.

Pages represent different landing points of your customers on your Tebex store. For example, when customers visit a category on your store, the category.html page will be rendered. For this reason, pages must be implemented in your templates and cannot be deleted (unlike [Assets](/developers/templates/assets)).

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)

The only pages that are not accessible to the public are the following:

| Page        |                                                                                                                                                                                 |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| layout.html | This is the global layout of your store that all pages extend from. You are able to create multiple layouts if you wish via creating an [Asset](/developers/templates/assets).  |
| module.\*   | These pages are used to build the Sidebar modules of your store, and you can view more information within the [Sidebar Modules](/developers/templates/sidebar-modules) section. |


# index.html

The index.html page is the homepage of your store.

### Root Object

| Variables     | Type   | Description                        |
| ------------- | ------ | ---------------------------------- |
| `description` | string | The homepage content of the store. |

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# checkout.html

There is no specific variables for checkout.html. All checkout functionality is handled via opening a new [Tebex.js](/developers/tebex.js/overview) session. To start a new Checkout session, you should do the following:

1. [Add Tebex.js to your store](/developers/tebex.js/overview)&#x20;
2. [Receive the current baskets ident](#receive-an-ident-for-tebex.js)
3. [Launch the Tebex.js modal](#using-tebex.js)

### Receive an ident for Tebex.js

<mark style="color:green;">`GET`</mark> `/checkout/ident`

This endpoint will return an ident for the current basket, which is required by [Tebex.js](/developers/tebex.js/overview) when launching a checkout modal.

**Response**

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

```json
{
    "ident":"null if customer is not logged in"
}
```

{% endtab %}
{% endtabs %}

### Using Tebex.js

To learn how to add Tebex.js to your store, please view the [associated documentation](/developers/tebex.js/overview) or view the demo over at <https://js.tebex.io>.


# username.html

The username.html page is responsible for allowing your customers login to your store.

### Root Object

| Variables | Type    | Description                                                                                                                                                                                                                 |
| --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| external  | Boolean | If the login provider of the store requires the user to be sent to an external url which is available in the `url` variable. See [Non-External Login](#non-external-login) for what to do in the event external is `false`. |
| provider  | String  | The name of the login provider, such as FiveM, Discord or Steam.                                                                                                                                                            |
| url       | String  | The URL that the customer should be directed to so they can perform their login with the external provider.                                                                                                                 |

### External Login

If the external variable is `true`, let the user click a link to proceed to login via the external login provider:

```html
<p>Please login with your {{ provider }} account to continue.</p>
<a href="{{ url }}">Login</a>
```

### Non-External Login

If the external variable is `false`,  provide a form submitting to the current url, including an `ign` form parameter. The `ign` parameter should be a text field allowing the customer to enter their username freehand.

An example can be seen below:

```html
<form method="post">
    <input type="text" name="ign" placeholder="Enter your in-game username" />
    <button type="submit">Login</button>
</form>
```

### Full Working Example

An example of a flow supporting both external and non-external login providers is shown below:

```twig
{% if external %}
    <a href="{{ url }}">Login via {{ provider }}</a>
{% else %}
    <form method="post">
        <input
            type="text"
            name="ign"
            placeholder="Enter your in-game username"
        />
        <button type="submit">Login</button>
    </form>
{% endif %}
```

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# options.html

The options.html page is shown to the customer when adding a package that requires customisation, such as when you are using [variables](https://creator.tebex.io/variables).&#x20;

### Root Object

<table><thead><tr><th width="326.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>options.package</code></td><td><a href="#package-object">Package Object</a></td><td>An object containing information about the current package.</td></tr><tr><td><code>options.variables</code></td><td>array[<a href="#variable-object">Variable</a>]</td><td>An array containing the <a href="https://creator.tebex.io/variables">variables</a> the customer needs to select.</td></tr></tbody></table>

### Package Object

<table><thead><tr><th width="305">Variable</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>string</td><td>The name of the package.</td></tr><tr><td><code>chooseServer</code></td><td>boolean</td><td>If the package requires the customer to select a <a href="https://creator.tebex.io/game-servers">game server</a>.</td></tr><tr><td><code>customPrice</code></td><td>boolean</td><td>If the package requires the customer to enter how much they want to pay for the package.</td></tr><tr><td><code>category</code></td><td>string</td><td>The category ID of the package.</td></tr><tr><td><code>price</code></td><td>string</td><td>The price of the package.</td></tr></tbody></table>

## Variable Object

<table><thead><tr><th width="308">Variable</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>description</code></td><td>string</td><td>A summary of the description of the variable.</td></tr><tr><td><code>type</code></td><td>string</td><td>Either <code>dropdown</code>, <code>discord_id</code>, or show an input field for freehand input by the customer.</td></tr><tr><td><code>id</code></td><td>string</td><td>The ID of the variable.</td></tr><tr><td><code>options</code></td><td>array[<a href="#variable-option-object">Variable Option</a>]</td><td>If the type is <code>dropdown</code>, we include an array of options the customer should select from.</td></tr><tr><td><code>value</code></td><td>string</td><td>The current value of the variable.</td></tr><tr><td><code>discord_tag</code></td><td>string</td><td>If the variable is type is <code>discord_id</code> and the <code>value</code> is not empty, this will include their discord tag once they have logged in.</td></tr></tbody></table>

### Variable Option Object

<table><thead><tr><th width="277">Variable</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>default</code></td><td>boolean</td><td>If this variable option should be selected by default.</td></tr><tr><td><code>name</code></td><td>string</td><td>The name of the dropdown option.</td></tr><tr><td><code>price</code></td><td>string</td><td>The additional price the customer would pay by selecting this variable option.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# package.html

The package.html page displays details about a specific [package](https://creator.tebex.io/packages) on your store.

### Root Object

<table><thead><tr><th width="345.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>string</td><td>The ID of the package.</td></tr><tr><td><code>identifier</code></td><td>string</td><td>The slug of the package. Defaults to the numeric ID if no slug is defined.</td></tr><tr><td><code>name</code></td><td>string</td><td>The name of the package.</td></tr><tr><td><code>description</code></td><td>string</td><td>The description of the package.</td></tr><tr><td><code>customPrice</code></td><td>boolean</td><td>If the package can have a custom price.</td></tr><tr><td><code>price</code></td><td>string</td><td>The price of the package.</td></tr><tr><td><code>purchasable</code></td><td>boolean</td><td>If the currently logged in customer is allowed to purchase this package on your store.</td></tr><tr><td><code>quantity</code></td><td>integer</td><td>The quantity of this package in the customers basket.</td></tr><tr><td><code>image.url</code></td><td>string</td><td>The public url of the packages image hosted on the Tebex CDN.</td></tr><tr><td><code>image.uploaded</code></td><td>boolean</td><td>If this package has an image uploaded.</td></tr><tr><td><code>category</code></td><td>string</td><td>The ID of the category which this package belongs to.</td></tr><tr><td><code>has_options</code></td><td>boolean</td><td>If this package requires options to be entered/selected before adding to the basket.</td></tr><tr><td><code>discount.applied</code></td><td>boolean</td><td>If the package has a discount applied.</td></tr><tr><td><code>discount.original</code></td><td>string</td><td>The original price of the package before the discount was applied.</td></tr><tr><td><code>discount.percentage</code></td><td>string</td><td>The percentage equivalent of the discount applied to the package.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# cms/page.html

The cms/page.html page displays any [custom pages](https://creator.tebex.io/pages) that you have created on your store.

### Root Object

| Variables          | Type   | Description                     |
| ------------------ | ------ | ------------------------------- |
| `id`               | string | The ID of the page.             |
| `category`         | string | The category of the page.       |
| `title`            | string | The title of the page.          |
| `metaData.content` | string | The actual content of the page. |

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# category.html

The category.html page lists the [packages](https://creator.tebex.io/packages) that are available to purchase in the current category being viewed on your store.

### Root Object

| Variable      | Type   | Description                                                              |
| ------------- | ------ | ------------------------------------------------------------------------ |
| `id`          | string | The ID of the category.                                                  |
| `name`        | string | The name of the category.                                                |
| `displayType` | string | The display type (either grid or list)                                   |
| `description` | string | The description of the category.                                         |
| `packages`    | array  | An array of [Package Objects](/developers/templates/pages/package.html). |
| `slug`        | string | The url slug of the category.                                            |

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# layout.html

There isn't any specific variables for layout.html. This page is usually extended by all other pages, providing your stores base layout structure.

An example of using layout.html can be seen below:

### layout.html

```twig
<!DOCTYPE html>
<html>
    <body>
        {% block content %}{% endblock %} {# The content of checkout.html will be shown #}
    </body>
</html>
```

### checkout.html

```twig
{% extends "layout.html" %}

{% block content %}
    Hello, world!
{% endblock %}
```


# Sidebar Modules

Dynamic modules to display useful information on your store.

Modules allow you to add dynamic modules on your store, which you can configure from within your creator panel on the [sidebar](https://creator.tebex.io/sidebar) section.

Each modules HTML is configurable in their associated `module.*.html` page (documented onwards).&#x20;

You can display the modules on your store by printing the modules variable, as seen below:

```twig
{{ modules|raw }}
```

{% hint style="info" %}
Please ensure to use the `raw` [filter](/developers/templates/twig/filters), as the `modules` variable contains HTML that will be escaped automatically by TWIG if this filter is not used.
{% endhint %}


# module.communitygoal.html

The community goal module displays the current progress of a community goal which you have configured within your creator panel on the [community goals](https://creator.tebex.io/community-goals) section.

<table><thead><tr><th width="429.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>module.header</code></td><td>string</td><td>The header of the module.</td></tr><tr><td><code>module.communitygoal.image</code></td><td>string</td><td>The URL of the image of the community goal hosted on our public CDN.</td></tr><tr><td><code>module.communitygoal.repeatable</code></td><td>boolean</td><td>If the community goal is repeatable.</td></tr><tr><td><code>module.communitygoal.times_achieved</code></td><td>string</td><td>The number of times the community goal has been reached.</td></tr><tr><td><code>module.communitygoal.description</code></td><td>string</td><td>The description of the community goal.</td></tr><tr><td><code>module.bar.style</code></td><td>string</td><td>The style of the goal, either striped or animated.</td></tr><tr><td><code>module.displayAmount</code></td><td>boolean</td><td>If the amount of the community goal should be displayed on your store.</td></tr><tr><td><code>module.total</code></td><td>string</td><td>The total the community goal has currently earned.</td></tr><tr><td><code>module.target</code></td><td>string</td><td>The target amount of the community goal.</td></tr><tr><td><code>module.percentage</code></td><td>string</td><td>The percentage equivalent of the current total against the target.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.featuredpackage.html

The featured package module allows you to feature a package, bringing more attention to it on your store.

| Variables        | Type                                                       | Description               |
| ---------------- | ---------------------------------------------------------- | ------------------------- |
| `module.header`  | string                                                     | The header of the module. |
| `module.package` | [Package Object](/developers/templates/pages/package.html) | The package to feature.   |

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.giftcardbalance.html

The gift card balance module lets your customers enter a gift card and determine the amount of value that remains on the specified gift card.

<table><thead><tr><th width="320.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>module.header</code></td><td>string</td><td>The header of the module.</td></tr><tr><td><code>search</code></td><td>boolean</td><td>If the customer has attempted to search for a giftcard.</td></tr><tr><td><code>giftcard</code></td><td>object</td><td>If a giftcard was found from their search, it will be populated in this object.</td></tr><tr><td><code>giftcard.card_number</code></td><td>string</td><td>The gift card number the customer has searched for.</td></tr><tr><td><code>giftcard.void</code></td><td>boolean</td><td>If the giftcard that has been searched for has been voided by the store owner.</td></tr><tr><td><code>giftcard.remaining_balance</code></td><td>string</td><td>The remaining balance of the giftcard which has been searched for.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.goal.html

The goal module allows you to show a goal of how much money you'd like to earn over a specific period.

<table><thead><tr><th width="307.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>module.header</code></td><td>string</td><td>The header of the module.</td></tr><tr><td><code>module.bar.style</code></td><td>string</td><td>The style of the module.</td></tr><tr><td><code>module.bar.animated</code></td><td>string</td><td>If the goal bar should be animated.</td></tr><tr><td><code>module.displayAmount</code></td><td>boolean</td><td>If to display the amount instead of just a percentage.</td></tr><tr><td><code>module.total</code></td><td>string</td><td>The total amount earned so far towards the goal.</td></tr><tr><td><code>module.target</code></td><td>string</td><td>The target of the goal.</td></tr><tr><td><code>module.percentage</code></td><td>string</td><td>The percentage towards completion of the goal.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.payments.html

The payments module allows you to display a selection of recent payments received from customers on your store.

<table><thead><tr><th width="297.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>module.header</code></td><td>string</td><td>The header of the module.</td></tr><tr><td><code>module.payments</code></td><td>array[<a href="#payment-object">Payment</a>]</td><td>An array of payments.</td></tr><tr><td><code>module.displayPackage</code></td><td>boolean</td><td>If to display the package names against each payment.</td></tr><tr><td><code>module.displayPrice</code></td><td>boolean</td><td>If to display the price of each payment.</td></tr></tbody></table>

### Payment Object

| Variable   | Type   | Description                                         |
| ---------- | ------ | --------------------------------------------------- |
| `ign`      | string | The username of the customer.                       |
| `name`     | string | The name of the package the customer has purchased. |
| `time`     | string | The time the purchase was received on the store.    |
| `price`    | string | The amount of the purchase.                         |
| `currency` | string | The currency of the purchase.                       |

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.serverstatus.html

The server status module allows creators who operate Game Servers to display the status of their game server (e.g. player count or online status) on their store.

<table><thead><tr><th width="298.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>module.header</code></td><td>string</td><td>The header of the module.</td></tr><tr><td><code>module.online</code></td><td>boolean</td><td>If the game server is online.</td></tr><tr><td><code>module.ip</code></td><td>string</td><td>The IP address of the game server.</td></tr><tr><td><code>module.port</code></td><td>string</td><td>The port of the game server.</td></tr><tr><td><code>module.players.online</code></td><td>string</td><td>The total players on the game server.</td></tr><tr><td><code>module.players.max</code></td><td>string</td><td>The maximum players that can be online at one point on the game server.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.textbox.html

The textbox module allows a store owner to define a module with arbitrary text.

| Variables       | Type   | Description                        |
| --------------- | ------ | ---------------------------------- |
| `module.header` | string | The header of the module.          |
| `module.text`   | string | The content of the textbox module. |

{% hint style="info" %}
Please ensure to use the `raw` [filter](/developers/templates/twig/filters) on the `module.text` variable as it contains HTML and will be automatically escaped by TWIG if not used.
{% endhint %}

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# module.topdonator.html

The top donator module allows you to display the highest spending customer on your store.

<table><thead><tr><th width="318.3333333333333">Variables</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>module.header</code></td><td>string</td><td>The header of the module.</td></tr><tr><td><code>module.donor</code></td><td>boolean</td><td>If there is actually a top customer to show yet.</td></tr><tr><td><code>module.skin</code></td><td>string</td><td>The URL of the customers profile image to display.</td></tr><tr><td><code>module.ign</code></td><td>string</td><td>The username of the customer.</td></tr><tr><td><code>module.displayAmount</code></td><td>boolean</td><td>If to display the amount the customer has spent on your store.</td></tr><tr><td><code>module.total</code></td><td>string</td><td>The total amount the customer has spent on your store.</td></tr><tr><td><code>module.period</code></td><td>string</td><td>The period which calculates the above total. Can be either hourly, daily, weekly, monthly or yearly.</td></tr></tbody></table>

### Request Variable

If you'd like access to a variable that is not currently available, [please let us know.](https://forms.monday.com/forms/8cbacdac7c30b725cd4617cbba0e5eeb?r=use1)


# Assets

Upload custom CSS, Javascript, Images or Twig files to your store for public access.

Assets allow you to upload your own CSS, Javascript, Images or Twig files to your template, which you can later reference in your files.

To create an asset, first upload it from within the template editor. Once you have uploaded the asset, you can retrieve the public URL of the asset by using the`asset()` function. This function will return the full URL of the asset hosted on our global CDN.

For example, you could upload `scripts.js` as an asset, and then include it in your template:

```twig
<script defer src="{{ asset('scripts.js') }}"></script>
```

You're also able to create TWIG files that you can later reference in your template. For example, you could create an asset called `navigation.twig`, and then include it using the Twig include tag:

```twig
{% include "navigation.twig" %}
```

This allows you to create code that is easily reusable across multiple locations in your template.


# Schema

No-code customisation for your template directly from within the creator panel.

A template schema allows other team members or consumers of your template to change its appearance, for example providing colour pickers to change the colours of your template without the need to edit the CSS or HTML manually. This is especially useful if you are a template designer and you're selling access to your custom template for many different stores to use.

To edit the schema of a template, first open the template editor and select the **Change Schema** page from the navigation on the left. Any config options you add within the schema will appear within the Appearance section of the creator panel when you click edit on the template.

A great example of Schema in action would be to look at the configuration options available with our default template, Exo, which you can view in the [creator panel](https://creator.tebex.io/templates/187300).

## Example Schema

```json
{
  "author": "Tebex",
  "support_email": "support@tebex.io",
  "config": [
    {
      "header": "Customize Template",
      "options": [
        {
          "id": "nav-style",
          "name": "Navigation Style",
          "description": "Set the location for your navigation.",
          "type": "select",
          "default": "Vertical Nav in Sidebar",
          "values": [
            "Horizontal Nav in Header",
            "Vertical Nav in Sidebar"
          ]
        },
        {
          "id": "server-ip",
          "name": "Server IP",
          "default": "",
          "description": "Enter your server IP - it will be used in the copy server IP section.",
          "type": "textarea"
        },
        {
          "id": "discord",
          "name": "Discord",
          "default": "",
          "description": "Enter your Discord invite url - it will be used in the header Discord section.",
          "type": "textarea"
        }
      ]
    }
  ]
}
```

## Available Config Types

You're able to implement several different types of config options within your template schema, from colour pickers to text boxes.

<details>

<summary>Colour Picker</summary>

Displays a colour picker for selecting a custom HEX code.

```json
{
   "id": "primary-colour",
   "name": "Primary Colour",
   "default": "#0000FF",
   "description": "Select your primary colour.",
   "type": "colour-picker"
}
```

</details>

<details>

<summary>File Uploader</summary>

Display a file upload option, useful for favicons, or other assets.

```json
{
   "id": "my-file",
   "name": "My File",
   "default": "",
   "description": "Upload a file.",
   "type": "file"
}
```

</details>

<details>

<summary>Image Uploader</summary>

Display an image uploader config option.

```json
{
   "id": "custom-image",
   "name": "Custom Image",
   "default": "",
   "description": "Upload an image here.",
   "type": "image-uploader"
}
```

</details>

<details>

<summary>Select</summary>

Display a select dropdown to allow the store to select from multiple options.

```json
{
   "id": "nav-style",
   "name": "Navigation Style",
   "description": "Set the location for your navigation.",
   "type": "select",
   "default": "Vertical Nav in Sidebar",
   "values": [
       "Horizontal Nav in Header",
       "Vertical Nav in Sidebar"
    ]
}        
```

</details>

<details>

<summary>Slider</summary>

Display a slider to allow the store to select between a range of numbers - useful for customising.

```json
{
   "id": "width",
   "name": "Button Width",
   "default": "",
   "description": "Select the width of buttons.",
   "type": "slider",
   "min": 0,
   "max": 100
}
```

</details>

<details>

<summary>Textarea</summary>

```json
{
   "id": "header-box",
   "name": "Header Content",
   "default": "",
   "description": "Enter the text you'd like to appear in the header.",
   "type": "textarea"
}
```

</details>

<details>

<summary>Url</summary>

```json
{
   "id": "discord-link",
   "name": "Discord Invite Link",
   "default": "",
   "description": "Enter the URL of your discord invite link.",
   "type": "url"
}
```

</details>

## Accessing Config Options

To dynamically access the config option from within your template you can use the [`config()`](/developers/templates/twig/functions#config) Twig function. This will output the entered option value, allowing you to use it however you wish within your template, such as outputting a text area into a specific location or altering CSS via a colour picker.


# Developer Plan

Let us support you develop custom templates for Tebex creators.

If you're a template developer, you're entitled to receive free Tebex Plus to enable you to freely develop templates for your clients. Stores that receive our developer plan won't be able to transact real payments on their store.

You're also eligible to gain access to the certified Tebex designers club. You'll get insider help guides, access to a private community of other elite designers, feedback sessions with the Tebex product team, and also BETA features that are not yet available to others.

If you'd like to apply to become a Tebex Certified Designer, [please apply here](https://forms.monday.com/forms/fce1c5555703d90861656cd5571d5543?r=use1).


# Footer

Upon creating your store you may notice the footer at the bottom of your store stating that it is powered by Tebex and that we are the reseller & merchant of record.

Hiding the footer on your webstore will void our terms and conditions and will result in us having to disable your store from the public.

As a merchant of record platform we are under strict requirements by the card networks, such as Visa & Mastercard, to ensure customers understand which company they are purchasing from. You are authorising Tebex to operate a webstore on your behalf and sell content that we license from you, thus we need to let customers know about this as clearly as possible.&#x20;

We don't place the footer for our own marketing/branding benefit - we simply have to do it to be able to provide you with all the benefits you receive as us being the Merchant Of Record, such as:

1. 100 payment method integrations
2. Sales tax collection and remittance worldwide
3. Fraud protection & our chargeback guarantee
4. Easy to integrate product delivery for your game studio & server

## Styling the footer to match your own brand

The colour scheme of the footer by default matches your Tebex Checkout theme. You're able to select between Dark or Light mode by viewing your Checkout settings within the creator panel.

The footer also listens to the following CSS variables which you can define in your template/theme, providing you with further customisation ability:

| Variable                              |
| ------------------------------------- |
| --tebex-legal-footer-background-color |
| --tebex-legal-footer-text-color       |
| --tebex-legal-footer-border-color     |
| --tebex-legal-footer-max-width        |
| --tebex-legal-footer-logo-color       |

An example of setting the CSS variables can be seen below, which you could place in your templates CSS file:

```css
:root {
  --tebex-legal-footer-background-color: #fcba03;
  --tebex-legal-footer-text-color: #4c00ff;
}
```


# Guides

Guides to help keep your custom template up-to-date.

In order to support certain features of Tebex, your custom template must be kept up-to-date. Please see the following guides:

{% content-ref url="/pages/zjFr28AF3P3W3PR8TDEW" %}
[Package Slugs](/developers/templates/guides/package-slugs)
{% endcontent-ref %}


# Package Slugs

Package slugs allow you to customize your package's URL slug for better readability.

If you are using a custom template, you may need to update it to ensure the package slugs feature functions correctly on your webstore.

### Template Changes

In your Twig templates, any instance of `package.id` should be updated to `package.identifier`. This property will use the package’s slug if available and default to the numeric ID if not.


# Supporting Tiers on Custom Store Templates

If you are using a custom or legacy store template, **Tiered** packages may not display properly once enabled on your store.

If you are using Exo or a Premium template, this guide does not apply.

For tiers to display on your store, create the following **Assets**:

1. `category/tiered.html`  - HTML structure for a tiered category
2. `quote.html` - HTML confirmation page when updating a tier

Use the following examples to add **Tiers** support to your store:

## category/tiered.html

```html
{% extends "layout.html" %}

{% block content %}
<div class="site-content site-content-widgets" style="max-width: 1140px; margin: 0 auto; padding: 1rem;">
  <main class="store-category-tiered">
    <header class="store-category-tiered-header text-content">
      <h2>{{ category.name }}</h2>

      {% if category.description != "" %}
        <p>{{ category.description|raw }}</p>
      {% endif %}
    </header>

    {% if category.packages|length > 0 %}
      <div class="store-products-tiered" style="display: flex; flex-wrap: wrap;">
        {% for package in category.packages %}
          <article
            class="store-product store-product-tiered {{ (tier and tier.package_id == package.id) ? 'subscribed' : '' }}" style="display: flex; flex-direction: column; padding: 1rem;"
          >
            <img
              class="image"
              src="{{ package.image.url }}"
              alt="{{ package.name }}"
            />

            <h3 class="product-title">
              {{ package.name }}
              {% if package.countdownEnds %}
                <span
                  class="countdown"
                  data-countdown="{{ package.countdownEnds }}"
                >
                  {{__("Ending Soon!") }}
                </span>
              {% endif %}
            </h3>

            <div class="descr">
              {{ package.description|raw }}
            </div>            
            
            {% set packageIdentifier = package.identifier ? package.identifier : package.id %}

            <div
              class="actions product-actions"
              style="margin-top: auto;"
              data-package="{{ package.id }}"
              data-package-type="{{ package.type }}"
              {% if package.purchasable == false %}
                title="{{ package.reason }}"
              {% endif %}
            >
              <p class="price">
                {% if package.customPrice %}
                  {{ __("You decide how much to pay.") }}
                {% elseif package.price == 0.00 %}
                  <strong>{{ __("This item is free.") }}</strong>
                {% else %}
                  {% if package.discount.applied %}
                    <del class="text-danger small font-weight-bold">{{ package.discount.original|money }}</del>
                  {% endif %}

                  <strong>{{ package.price|money }}</strong> {{ basket.currency }}
                {% endif %}
              </p>

              {% if tier and tier.package_id == package.id %}
                <button class="btn btn-tertiary wide" disabled>
                  {{ __("Subscribed") }}
                </button>
              {% elseif tier and tier.downgrade_package_id == package.id %}
                <button class="btn btn-tertiary wide" disabled>
                  {{ __("Pending Downgrade") }}
                </button>
              {% elseif tier %}
                <a
                  href="/tier/quote?category={{ category.id }}&amp;package={{ package.id }}"
                  class="btn btn-primary wide"
                  {% if package.purchasable == false %}disabled{% endif %}
                  {% if package.basket %}hidden style="display: none;"{% endif %}
                >
                  {{ __("Subscribe") }}
                </a>
              {% else %}
                <a
                  href="/checkout/packages/add/{{ packageIdentifier }}/subscribe"
                  class="btn btn-primary subscribe wide"
                  {% if package.purchasable == false %}disabled{% endif %}
                  {% if package.basket %}hidden style="display: none;"{% endif %}
                >
                  {{ __("Subscribe") }}
                </a>
              {% endif %}

              <button
                class="btn btn-secondary wide open-basket open-basket-cta"
                {% if package.basket == false %}hidden style="display: none;"{% endif %}
              >
                {{ __("Added to Basket") }}
              </button>
            </div>
            
          </article>
        {% endfor %}
      </div>
    {% else %}
      <p>{{ __("No packages to display in this category.") }}</p>
    {% endif %}
  </main>
</div>
{% endblock %}
```

## quote.html

```html
{% extends "layout.html" %}

{% block content %}

<main class="store-quote store-form" data-popup style="max-width: 1140px; margin: 0 auto; padding: 1rem; text-align: center;">
  <div class="text-content">
    <h2>Update Tier</h2>
    {{ description|raw }}
  </div>

  <form method="post" action="/tier/update">
    <input type="hidden" name="category_id" value="{{ category }}">
    <input type="hidden" name="package_id" value="{{ package }}">

    {% for k, v in options %}
      <input type="hidden" name="options[{{ k }}]" value="{{ v }}">
    {% endfor %}

    <div class="actions quote-actions">
      <a href="/category/{{category}}" class="btn btn-tertiary wide">
        {{ __("Back") }}
      </a>
      <button type="submit" class="btn btn-primary wide confirm">
        {{ __("Confirm") }}
      </button>
    </div>
  </form>
</main>

{% endblock %}
```


# Supporting Package Media on Custom Store Templates

If you’re using a custom or legacy store template, you may not see all package images (when multiple images are uploaded) or the package video.

If you are using the Exo template, this guide does not apply.

Older templates relied on the `package.image` property to display a package’s image URL. To support package media properly, you now need to use the new `package.media` array instead. See the example code snippet below demonstrating how to use the new media array.

```html
{% for media in package.media %}
  <div class="slide">
    {% if media.type == 'image' %}
      <img
        class="slide-image"
        src="{{ media.url }}"
        alt="{{ package.name }}"
      />
    {% elseif media.type == 'video' %}
      <iframe
        class="slide-frame"
        src="https://www.youtube.com/embed/{{ media.url }}?color=white&amp;rel=0"
        title="YouTube video player"
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
        referrerpolicy="strict-origin-when-cross-origin"
        allowfullscreen
      ></iframe>
    {% endif %}
  </div>
{% endfor %}
```


# Introduction

Headless API is used to build custom frontends for your Tebex store, such as a website, app, or game.

The Headless API can retrieve your store's listings, create baskets, and send customers to checkout. It is the same API that backs Tebex-hosted webstores.

Like all Tebex APIs, it is a [RESTful API](http://en.wikipedia.org/wiki/Representational_State_Transfer) that uses JSON-encoded requests and responses. It is documented with [OpenAPI](https://www.openapis.org/), which is used as the foundation for our SDKs and the documentation seen here.

***API Specification:*** [*Tebex Headless OpenAPI Schema*](https://github.com/tebexio/TebexHeadless-OpenAPI/blob/main/headless-api.yaml)&#x20;

{% hint style="info" %}
Some endpoints may require prior approval or special account permissions. Please contact our support team if you encounter any issues.
{% endhint %}

## Getting Started

Tebex provides SDKs to streamline your development environment and make API calls. These SDKs contain mappings for all our APIs, not just Headless API.

We recommend using these to avoid writing boilerplate code and to automatically receive updates when the API changes.

{% tabs %}
{% tab title="Node.js" icon="node" %}

```shellscript
npm install tebexio/tebex-sdk-nodejs
```

{% endtab %}

{% tab title="PHP" icon="php" %}

```shellscript
composer require tebex/tebex-sdk-php
```

{% endtab %}

{% tab title="C#" icon="hashtag" %}

```bash
dotnet add package Tebex.CSharp --version 1.1.0
```

{% endtab %}
{% endtabs %}

If we do not have an official SDK in your language, the [OpenAPI generator](https://openapi-generator.tech/) can be used to generate the code to interact with Tebex APIs without starting from scratch.

## Using with Tebex.js

The Headless API can be used with [Tebex.js](/developers/tebex.js/overview) for a fully embedded checkout experience without the user ever leaving your own website.

## Examples

These projects use **Headless API** for part or all of their implementation and are open-source.

### Tebex Unity Demo

An in-game store browser UI, basket, and QR-code based checkout in Unity Engine.\
[Tebex for Unity Engine](/developers/tebex-for-unity-engine)

<figure><img src="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2F9Ly05gh5McZ6DETQ79Xk%2Fimage.png?alt=media&amp;token=e8596780-8d27-47e6-824e-cdde4735464a" alt=""><figcaption></figcaption></figure>

### Hytale Plugin

Hytale is a block-based survival game with a large private server community. Tebex provides an in-game store browser and cart with QR checkout, built on Headless API.

<https://github.com/tebexio/Tebex-Hytale>

<figure><img src="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2F5QapDOmlMZnxKxtGybdY%2Fimage.png?alt=media&amp;token=b0878e7c-1d63-49b6-8e76-40432d365e71" alt=""><figcaption></figcaption></figure>


# Authorization

Most Headless API endpoints **do not require authorization**.&#x20;

Auth may be required in cases where user data is returned, such as retrieving purchased Tiers.

When required, you'll need to use HTTP BASIC auth with the following details:

<table data-header-hidden><thead><tr><th width="243"></th><th></th></tr></thead><tbody><tr><td>Username <strong>(Public Token)</strong></td><td>Your Public Token (you can get this from <a href="https://creator.tebex.io/developers/api-keys">https://creator.tebex.io/developers/api-keys</a>)</td></tr><tr><td>Password <strong>(Private Key)</strong></td><td>Your Private Key (you can get this from <a href="https://creator.tebex.io/developers/api-keys">https://creator.tebex.io/developers/api-keys</a>)</td></tr></tbody></table>

{% hint style="info" %}
Your Public Token starts with 4 characters and a dash (ex. `spk3-d515a30...`)
{% endhint %}

{% hint style="danger" %}
The private key enables full access to your account. Follow best security practices to keep your keys safe. Don't embed any secret keys in your source code or client-side applications.&#x20;

If your key is ever compromised, it can be rotated in your Tebex panel [here](https://creator.tebex.io/developers/api-keys).
{% endhint %}


# Package Idents

Every package returned by the Headless API now has an `ident`: a string identifier that works for every package type.

Use it to refer to a package ( `packageId` ) whether you're fetching it or managing it in a basket.

{% hint style="info" %}
A numeric package `id` on a package can also work for identifying standard packages. We recommend switching to `ident` if you are using the numeric `id`.
{% endhint %}

### What an ident looks like

`ident` is returned on every package from these endpoints:

* `GET /packages`
* `GET /categories` and `GET /categories/{categoryId}` with `includePackages=1`
* `GET /packages/{packageId}`

```json
{
  "data": {
    "id": 456,
    "ident": "pkg_12_456",
    "name": "VIP Rank",
    "category": { "id": 12, "name": "Ranks" },
    ...
  }
}
```

Idents have the form `{prefix}_{categoryId}_{id}`:

| Prefix | Package type | Example               |
| ------ | ------------ | --------------------- |
| `pkg`  | Standard     | `pkg_12_456`          |
| `dyn`  | Dynamic      | `dyn_34_10`           |
| `ext`  | External     | `ext_10_{asset-uuid}` |

{% hint style="warning" %}
Store the package **`ident`** and use it in requests exactly as you received it - don't build idents yourself as the format may change.
{% endhint %}

#### External packages

For external packages, always use `ident`.

### Where you can use an ident

You can send an ident anywhere these endpoints take a package ID.

#### Get a package

```http
GET https://headless.tebex.io/api/accounts/{token}/packages/{packageId}
```

`{packageId}` can be an ident or a numeric ID:

```http
GET https://headless.tebex.io/api/accounts/{token}/packages/pkg_12_456
```

#### Add a package to a basket

```http
POST https://headless.tebex.io/api/baskets/{basketIdent}/packages
```

```json
{
  "package_id": "pkg_12_456",
  "quantity": 1
}
```

`package_id` can be an ident or a numeric ID. For external packages, it must be the ident.

#### Remove a package from a basket

```http
POST https://headless.tebex.io/api/baskets/{basketIdent}/packages/remove
```

```json
{
  "package_id": "pkg_12_456"
}
```

#### Update a package's quantity

```http
PUT https://headless.tebex.io/api/baskets/{basketIdent}/packages/{packageId}
```

```json
{
  "quantity": 2
}
```

`{packageId}` can be an ident or a numeric ID, for example `/packages/pkg_12_456`.

### Errors

When adding a package to a basket:

| Cause                                                                                            | Response                                                      |
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- |
| `package_id` isn't a valid package ID or ident                                                   | Validation error: `package_id must be a package ID or ident.` |
| The ident doesn't match a package in your store, or doesn't match the package's category or type | `400` `The selected id is invalid.`                           |

### Migrating from numeric IDs

1. Read `ident` from package responses wherever you currently read `id`.
2. Store `ident` in place of, or alongside, the numeric ID.
3. Send `ident` as `package_id` or `{packageId}` in the requests above.

Standard packages continue to accept numeric IDs, so you can migrate gradually. Support for external packages requires `ident`.


# Error Handling

Tebex uses traditional HTTP response codes to indicate success or failure:

* `2xx` codes indicate success
* `4xx` codes indicate an error with the information provided (bad request, no permissions)
* `5xx` codes indicate an error with Tebex servers

An [RFC-9457](https://www.rfc-editor.org/info/rfc9457/) compliant problem details object is returned containing details about the failure:

```json
{
    "type": "uri://path/to/problem/type",
    "title": "You do not have enough funds",
    "detail": "Your current funds are 30, but the cart is 50",
    "instance": "/account/token/baskets/tbx-abc123"
}
```


# Testing

There is no sandbox mode on Tebex. Instead, you use a **Test Payments** method in the production checkout flow which can be enabled/disabled as needed.

### Enable Test Mode

**Test Mode** is enabled from your store panel in [Settings → Checkout → Test Mode](https://creator.tebex.io/payment-methods/settings). This creates a **Test Payments** method that you can select at checkout that always succeeds.

Test payments and associated activity will create real records and create real webhook events.&#x20;

### Remove Test Payments

When you are done testing your store, these can be removed via [Settings → Checkout → Remove Test Payments](https://creator.tebex.io/payment-methods/settings)

{% hint style="danger" %}
Ensure that Test Payments are disabled before making your store available to the public.
{% endhint %}


# Guides


# Storefront


# Top Customers

## Get the webstore's top customer.

> Gets the customer who spent the most in the given period. This does not depend on the sidebar's Top Customer module being configured.\
> \
> Requires basic auth: the username is the webstore identifier and the password is the account's checkout API key.\
> \
> \- \`total\` is in the account's currency, net of tax, and matches the revenue statistics in the control panel.\
> \- Free, manual, zero-price and incomplete payments are never counted.\
> \- Responses are cached for 10 minutes.\
> \- If there is no top customer for the period, \`data\` is null.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"TopCustomerResponse":{"properties":{"data":{"$ref":"#/components/schemas/TopCustomer"}},"required":["data"]},"TopCustomer":{"properties":{"username":{"type":"string"},"username_id":{"type":"string"},"avatar_url":{"format":"uri","type":"string"},"total":{"description":"Amount spent in the period, in the account's currency, net of tax.","type":"number"},"currency":{"type":"string"},"period":{"description":"The period requested.","enum":["hourly","daily","weekly","monthly","yearly","none"],"type":"string"}},"required":["avatar_url","currency","period","total","username","username_id"]}}},"paths":{"/top-customers":{"get":{"description":"Gets the customer who spent the most in the given period. This does not depend on the sidebar's Top Customer module being configured.\n\nRequires basic auth: the username is the webstore identifier and the password is the account's checkout API key.\n\n- `total` is in the account's currency, net of tax, and matches the revenue statistics in the control panel.\n- Free, manual, zero-price and incomplete payments are never counted.\n- Responses are cached for 10 minutes.\n- If there is no top customer for the period, `data` is null.","operationId":"getTopCustomer","parameters":[{"description":"The period to rank customers over. `none` covers all time.","explode":true,"in":"query","name":"period","required":false,"schema":{"default":"monthly","enum":["hourly","daily","weekly","monthly","yearly","none"],"type":"string"},"style":"form"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopCustomerResponse"}}},"description":"Successful response returns the top customer, or null."}},"summary":"Get the webstore's top customer.","tags":["Headless"]}}}}
```


# Community Goals

## Get the webstore's community goals.

> Lists the store's community goals. This does not depend on the sidebar's Community Goal module being configured.\
> \
> Requires basic auth: the username is the webstore identifier and the password is the account's checkout API key.\
> \
> If there are no matching goals, \`data\` is an empty array.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"CommunityGoalsResponse":{"properties":{"data":{"description":"Community goals. Empty when none match.","items":{"$ref":"#/components/schemas/CommunityGoal"},"type":"array"}},"required":["data"]},"CommunityGoal":{"properties":{"id":{"type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image_url":{"format":"uri","nullable":true,"type":"string"},"target":{"description":"The goal amount, in `currency`.","type":"number"},"current":{"description":"The amount raised so far, in `currency`.","type":"number"},"currency":{"description":"The account currency.","type":"string"},"percentage":{"type":"number"},"repeatable":{"type":"boolean"},"times_achieved":{"type":"integer"},"last_achieved":{"format":"date-time","nullable":true,"type":"string"},"status":{"enum":["active","completed","disabled"],"type":"string"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["created_at","currency","current","description","id","image_url","last_achieved","name","percentage","repeatable","status","target","times_achieved","updated_at"]}}},"paths":{"/community-goals":{"get":{"description":"Lists the store's community goals. This does not depend on the sidebar's Community Goal module being configured.\n\nRequires basic auth: the username is the webstore identifier and the password is the account's checkout API key.\n\nIf there are no matching goals, `data` is an empty array.","operationId":"getCommunityGoals","parameters":[{"description":"Only return goals with these statuses, e.g. `status[]=active&status[]=completed`. A single `status=active` is also accepted. With no filter, all goals are returned.","explode":true,"in":"query","name":"status[]","required":false,"schema":{"items":{"enum":["active","completed","disabled"],"type":"string"},"type":"array"},"style":"form"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityGoalsResponse"}}},"description":"Successful response returns the community goals."}},"summary":"Get the webstore's community goals.","tags":["Headless"]}}}}
```

## Get a community goal.

> Gets a single community goal by its ID.\
> \
> Requires basic auth: the username is the webstore identifier and the password is the account's checkout API key.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"CommunityGoalResponse":{"properties":{"data":{"$ref":"#/components/schemas/CommunityGoal"}},"required":["data"]},"CommunityGoal":{"properties":{"id":{"type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image_url":{"format":"uri","nullable":true,"type":"string"},"target":{"description":"The goal amount, in `currency`.","type":"number"},"current":{"description":"The amount raised so far, in `currency`.","type":"number"},"currency":{"description":"The account currency.","type":"string"},"percentage":{"type":"number"},"repeatable":{"type":"boolean"},"times_achieved":{"type":"integer"},"last_achieved":{"format":"date-time","nullable":true,"type":"string"},"status":{"enum":["active","completed","disabled"],"type":"string"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["created_at","currency","current","description","id","image_url","last_achieved","name","percentage","repeatable","status","target","times_achieved","updated_at"]},"ErrorResponse":{"properties":{"type":{},"title":{"description":"A short, human-readable summary of the problem type.  It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization","type":"string"},"status":{"description":"The HTTP status code gen by the origin server for the occurrence of the problem.","type":"integer"},"detail":{"description":"A human-readable explanation specific to this occurrence of the problem.","type":"string"},"instance":{"description":"A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced","type":"string"}}}}},"paths":{"/community-goals/{communityGoalId}":{"get":{"description":"Gets a single community goal by its ID.\n\nRequires basic auth: the username is the webstore identifier and the password is the account's checkout API key.","operationId":"getCommunityGoal","parameters":[{"description":"The community goal ID.","explode":false,"in":"path","name":"communityGoalId","required":true,"schema":{"type":"integer"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityGoalResponse"}}},"description":"Successful response returns the community goal."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No community goal with that ID exists for this account."}},"summary":"Get a community goal.","tags":["Headless"]}}}}
```


# Recent Payments


# Baskets


# Get a Basket

## Get a basket

> Gets a basket associated with the provided identifier.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}":{"get":{"description":"Gets a basket associated with the provided identifier.","operationId":"getBasket","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response returns the basket information."}},"summary":"Get a basket","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```


# Create a Basket

For most stores, you can create a basket without any required parameters. For certain store types you may need to provide additional information.

### Minecraft and Overwolf Stores

You must provide the `username` parameter as part of the basket creation request so that the basket is attributed to the correct user.

The returned basket will contain a `username_id` which can safely be added to the user's session. It is required for use with certain endpoints across Tebex APIs.

### Backend Servers

If you are creating a basket on your backend server, you must provide an `ip_address`  on creation, otherwise the basket will be incorrectly attributed to your server's IP.

### Universal Stores

No `username` is required for your basket. Depending on your package **Deliverables** you may need to provide `variable_data` per each Package so that it is attributed to the correct user. See [Add Package to Basket](/developers/headless-api/guides/baskets/add-package-to-basket).

```json
{
  "complete_url": "https://example.tebex.io/thank-you",
  "cancel_url": "https://tebex.io/",
  "custom": {
    "foo": "bar"
  },
  "complete_auto_redirect": true,
  "ip_address": "127.0.0.1"
}
```

## Create a new basket

> Creates a new basket for use during checkout.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets":{"post":{"description":"Creates a new basket for use during checkout.","operationId":"createBasket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/createBasket_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response returns the basket information."},"422":{"description":"The provided webstore ID is invalid."}},"summary":"Create a new basket","tags":["Headless"]}}},"components":{"schemas":{"createBasket_request":{"properties":{"complete_url":{"description":"A URL the user can return to when checkout is completed.","type":"string"},"cancel_url":{"description":"A URL the user can return to when cancelling checkout.","type":"string"},"custom":{"description":"Custom data you wish to associate with the basket. This data will be included with webhook responses and GET requests associated with the Basket.","type":"object"},"complete_auto_redirect":{"description":"True if the user should automatically be redirected to the relevant complete/cancel URL","type":"boolean"}}},"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```


# Authorize a Basket

Depending on the type of Tebex store you are integrating, authorization may be required at checkout.

For most stores, the user must authorize their account before checkout is completed.&#x20;

This is done via the **/auth** endpoint where we will return the authentication options available for your store type.

Provide a `returnUrl` , and after successful authentication the user will be directed back to your site.

## Get auth links for basket

> Fetches a basket's auth URL. The player should be directed here in order for them to authorize their account.\
> When complete, they will be returned to the provided \`returnUrl\` and the basket will be authorized from that moment onwards.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/auth?returnUrl={returnUrl}":{"get":{"description":"Fetches a basket's auth URL. The player should be directed here in order for them to authorize their account.\nWhen complete, they will be returned to the provided `returnUrl` and the basket will be authorized from that moment onwards.","operationId":"getBasketAuthUrl","parameters":[{"$ref":"#/components/parameters/basketIdent"},{"description":"The URL you would like to redirect the user to after successful basket authentication.","explode":false,"in":"path","name":"returnUrl","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketAuthResponse"}}},"description":"Successful response returns the auth provider options and URLs of the sign-in link."},"422":{"description":"The provided webstore ID or basket ID is invalid."}},"summary":"Get auth links for basket","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"BasketAuthResponse":{"items":{"$ref":"#/components/schemas/BasketAuthResponse_inner"},"type":"array"},"BasketAuthResponse_inner":{"properties":{"name":{"type":"string"},"url":{"type":"string"}}}}}}
```

\#


# Add Package to Basket

To add a package, you must provide the `package_id` and the desired  `quantity`  of that package.

If your store uses **Dynamic Categories**, and the package you're adding is dynamic, then `dynamic` must be set to `true` or the request will fail.

{% hint style="info" %}
Modifying package quantities after adding requires authentication. See [Authorize a Basket](/developers/headless-api/guides/baskets/authorize-a-basket)
{% endhint %}

## Add package to basket

> Add a package to the basket by its \`ident\` or numeric ID.\
> \
> \- Using \`ident\` is recommended, since it works for every package type. It is required for external packages.\
> \- Numeric IDs still work for standard packages.\
> \
> To add a package belonging to a dynamic category, set \`dynamic\` to \`true\`. Without this property the API will treat the request as a normal package ID.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Endpoints requiring only a basket ident with no token","name":"Baskets"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/{basketIdent}/packages":{"post":{"description":"Add a package to the basket by its `ident` or numeric ID.\n\n- Using `ident` is recommended, since it works for every package type. It is required for external packages.\n- Numeric IDs still work for standard packages.\n\nTo add a package belonging to a dynamic category, set `dynamic` to `true`. Without this property the API will treat the request as a normal package ID.","operationId":"addBasketPackage","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/addBasketPackage_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The ident is unknown or does not match a package in this store (\"The selected id is invalid.\")."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation. A malformed `package_id` fails with \"package_id must be a package ID or ident.\""}},"summary":"Add package to basket","tags":["Baskets"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"addBasketPackage_request":{"properties":{"package_id":{"description":"The package's `ident` (recommended) or numeric ID. `ident` is required for external packages. Send the `ident` exactly as returned by the package endpoints.","type":"string"},"quantity":{"type":"integer"},"dynamic":{"description":"Set to `true` when adding a package that belongs to a dynamic category. When omitted, the API acts as if a normal package ID was provided.","type":"boolean"}},"required":["package_id","quantity"]},"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}},"ErrorResponse":{"properties":{"type":{},"title":{"description":"A short, human-readable summary of the problem type.  It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization","type":"string"},"status":{"description":"The HTTP status code gen by the origin server for the occurrence of the problem.","type":"integer"},"detail":{"description":"A human-readable explanation specific to this occurrence of the problem.","type":"string"},"instance":{"description":"A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced","type":"string"}}}}}}
```


# Variable Data

**Variables** can be added to your store from your Creator Panel, which will add additional options for the user to select per-package.

There are certain system variables which may be required depending on the **Package** deliverables:&#x20;

### Gift Cards

When a package delivers a gift card to the user, include a `giftcard_to` with the email address that should receive the gift card:

```json
{
    "package_id": "6276316",
    "quantity": 1,
    "variable_data": {
        "giftcard_to": "tebex-integrations@overwolf.com"
    }
}
```

### Discord Actions

Include the user's `discord_id` for packages that trigger a Discord action:

```json
{
    "package_id": "6276316",
    "quantity": 1,
    "variable_data": {
        "discord_id": "000000000000000000"
    }
}
```

### Game Server Commands

Packages that deliver game server commands should include the `username_id` of the user.

{% hint style="info" %}
The `username_id` is returned at basket creation so long as the `username` was provided with the create request.
{% endhint %}

#### Specify Game Server

Game server commands can be configured to  `Allow customers to select the game server they want to receive this package on.`&#x20;

You can specify the target game server in the request by including `server` in your package's `variable_data` with the associated server id:

```json
{
    "package_id": "6276316",
    "quantity": 1,
    "variable_data": {
        "server": "127444"
    }
}
```

A list of your server IDs can be found in your [Tebex Control Panel](https://creator.tebex.io/game-servers) by clicking **Edit** beside your relevant game server. The server ID is the number at the end of the URL when editing the game server.


# Custom Data

Tebex supports `custom` data when adding packages to the basket. All `custom` data will be returned to you in associated Webhooks that deliver basket information.

```json
{
    "package_id": "6276316",
    "quantity": 1,
    "variable_data": {
        "username_id": "9e65a968ee4743d19a2a4c9969154491"
    },
    "custom": {
        "key": "value"
    }
}
```

Custom data is useful to assist with integration into your own systems.&#x20;

Common use cases for custom data include custom user identifiers. Your website could authorize a user in-house, then attach their user ID which will be provided to all webhook receivers. This would enable your backend server to quickly reference your internal models.


# Gifting Packages

If **Allow Gifting** is enabled, players can gift packages to other players. This is enabled in your store settings at [**Settings → Checkout**](https://creator.tebex.io/payment-methods/settings).

Include `target_username_id` , or `target_username` **when adding the package to the basket** and the package will be delivered to that player rather than the buyer.

The **target\_username\_id** should be a unique identifier for the player instead of their name (such as a Minecraft UUID or Steam ID):

```json
{
    "package_id": "6276316",

    // provide ONE of these:
    "target_username_id": "069a79f444e94726a5befca90e38aaf5",
    "target_username": "TebexDev"
}
```

{% hint style="warning" %}
Bedrock and Geyser stores must provide **target\_username** instead of the UUID due to differences in player IDs between Minecraft: Java Edition and Minecraft: Bedrock Edition.
{% endhint %}


# Remove Package from Basket

To remove a package from the basket, provide the `package_id` . This will remove the package entirely, it does not decrement the quantity count. For that, use [Update Package Quantity](/developers/headless-api/guides/baskets/update-package-quantity).

## Remove a package from a basket

> Remove a package from the basket by its \`ident\` or numeric ID.\
> \
> \- Using \`ident\` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\
> \- Numeric IDs still work for standard packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Endpoints requiring only a basket ident with no token","name":"Baskets"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/{basketIdent}/packages/remove":{"post":{"description":"Remove a package from the basket by its `ident` or numeric ID.\n\n- Using `ident` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\n- Numeric IDs still work for standard packages.","operationId":"removeBasketPackage","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/removeBasketPackage_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response returns the basket."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Remove a package from a basket","tags":["Baskets"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"removeBasketPackage_request":{"properties":{"package_id":{"description":"The package's `ident` (recommended) or numeric ID.","type":"string"}}},"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```


# Update Package Quantity

Set the quantity of an item in the basket

You will provide the basket and package ID being modified and a `quantity` value reflecting the user's desired quantity of that package.

{% hint style="info" %}
The user must be authorized before package quantities can be changed, otherwise the request will fail. See [Authorize a Basket](/developers/headless-api/guides/baskets/authorize-a-basket)
{% endhint %}

## Update package quantity

> Sets the quantity of the given item in the basket. The user must be logged in before the quantity can be changed.\
> \
> \- \`{packageId}\` accepts the package's \`ident\` or numeric ID. Using \`ident\` is recommended, since it works for every package type.\
> \- Numeric IDs still work for standard packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Endpoints requiring only a basket ident with no token","name":"Baskets"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/{basketIdent}/packages/{packageId}":{"put":{"description":"Sets the quantity of the given item in the basket. The user must be logged in before the quantity can be changed.\n\n- `{packageId}` accepts the package's `ident` or numeric ID. Using `ident` is recommended, since it works for every package type.\n- Numeric IDs still work for standard packages.","operationId":"updatePackageQuantity","parameters":[{"$ref":"#/components/parameters/basketIdent"},{"description":"The package's `ident` (recommended) or numeric ID.","explode":false,"in":"path","name":"packageId","required":true,"schema":{"type":"string"},"style":"simple"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updatePackageQuantity_request"}}}},"responses":{"200":{"description":"Successful response."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Update package quantity","tags":["Baskets"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"updatePackageQuantity_request":{"properties":{"quantity":{"type":"integer"}}}}}}
```


# Sales


# Get Sales

## Get the webstore's active sales.

> Lists the store's currently active sales, in the same order as the control panel. No authentication is required.\
> \
> \- Only sales whose start/end window includes the current time are returned. Expired sales, future sales and Lighthouse sales are left out.\
> \- Hidden packages and categories (disabled, removed, unpublished, or inside a disabled category) are left out of every array.\
> \- If there are no active sales, \`data\` is an empty array.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/sales":{"get":{"description":"Lists the store's currently active sales, in the same order as the control panel. No authentication is required.\n\n- Only sales whose start/end window includes the current time are returned. Expired sales, future sales and Lighthouse sales are left out.\n- Hidden packages and categories (disabled, removed, unpublished, or inside a disabled category) are left out of every array.\n- If there are no active sales, `data` is an empty array.","operationId":"getSales","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesResponse"}}},"description":"Successful response returns the active sales."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The store identifier is invalid."}},"summary":"Get the webstore's active sales.","tags":["Headless"]}}},"components":{"schemas":{"SalesResponse":{"properties":{"data":{"description":"Active sales, in control panel order. Empty when there are none.","items":{"$ref":"#/components/schemas/Sale"},"type":"array"}},"required":["data"]},"Sale":{"properties":{"id":{"type":"integer"},"name":{"type":"string"},"starts_at":{"description":"Start of the sale, ISO 8601 in UTC.","format":"date-time","type":"string"},"ends_at":{"description":"End of the sale, ISO 8601 in UTC.","format":"date-time","type":"string"},"discount":{"$ref":"#/components/schemas/SaleDiscount"},"applies_to":{"$ref":"#/components/schemas/SaleAppliesTo"},"requirements":{"description":"Conditions a customer must meet for the sale to apply. Empty when the sale has none. `minimum_basket_value` can appear alongside `purchased_packages` or `lifetime_spend`.","items":{"$ref":"#/components/schemas/SaleRequirement"},"type":"array"}},"required":["applies_to","discount","ends_at","id","name","requirements","starts_at"]},"SaleDiscount":{"properties":{"type":{"enum":["percentage","amount","commands"],"type":"string"},"percentage":{"description":"Set only when `type` is `percentage`, otherwise null.","nullable":true,"type":"number"},"amount":{"description":"Set only when `type` is `amount`, otherwise null.","nullable":true,"type":"number"},"currency":{"description":"The store currency.","type":"string"}},"required":["amount","currency","percentage","type"]},"SaleAppliesTo":{"description":"What the sale applies to. Only the array matching `type` is filled; the others are empty. When `type` is `all`, only `excluded_packages` may be filled.","properties":{"type":{"enum":["all","package","category","variable_option"],"type":"string"},"packages":{"description":"Filled when `type` is `package`.","items":{"$ref":"#/components/schemas/SaleReference"},"type":"array"},"categories":{"description":"Filled when `type` is `category`.","items":{"$ref":"#/components/schemas/SaleReference"},"type":"array"},"variable_options":{"description":"Filled when `type` is `variable_option`.","items":{"$ref":"#/components/schemas/SaleReference"},"type":"array"},"excluded_packages":{"description":"Packages excluded from the sale. Filled only when `type` is `all`.","items":{"$ref":"#/components/schemas/SaleReference"},"type":"array"}},"required":["categories","excluded_packages","packages","type","variable_options"]},"SaleReference":{"description":"A package, category or variable option referenced by a sale.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"required":["id","name"]},"SaleRequirement":{"description":"A condition for the sale. Fields present depend on `type`:\n- `purchased_packages`: `packages` and `match` (always `all`). `packages` is empty if every required package is hidden.\n- `lifetime_spend`: `amount` and `currency`.\n- `minimum_basket_value`: `amount` and `currency`.","properties":{"type":{"description":"The type of requirement for the sale. Additional requirement types may be added later. Clients must ignore requirement types they do not know.","enum":["purchased_packages","lifetime_spend","minimum_basket_value"],"type":"string"},"packages":{"description":"Packages the customer must have purchased. Present for `purchased_packages`.","items":{"$ref":"#/components/schemas/SaleReference"},"type":"array"},"match":{"description":"Present for `purchased_packages`. Always `all`.","enum":["all"],"type":"string"},"amount":{"description":"Present for `lifetime_spend` and `minimum_basket_value`.","type":"number"},"currency":{"description":"Present for `lifetime_spend` and `minimum_basket_value`. The store currency.","type":"string"}},"required":["type"]},"ErrorResponse":{"properties":{"type":{},"title":{"description":"A short, human-readable summary of the problem type.  It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization","type":"string"},"status":{"description":"The HTTP status code gen by the origin server for the occurrence of the problem.","type":"integer"},"detail":{"description":"A human-readable explanation specific to this occurrence of the problem.","type":"string"},"instance":{"description":"A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced","type":"string"}}}}}}
```


# Basket Links

**BasketLinks** are the available links for a given basket. When a customer is ready to checkout, they can be directed to the `checkout` URL.

## The BasketLinks object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```


# Categories


# Get Categories

Categories contain your store's **Packages**, allowing you to group packages in the order you desire.

You can fetch just the store categories or include the packages with the response as well. [Get Categories Include Packages](/developers/headless-api/guides/categories/get-categories-include-packages)

{% hint style="info" %}
Categories can be nested within other categories. A `parent` parameter is provided with details of the parent category, if applicable.
{% endhint %}

## Get all categories

> Gets all categories from a webstore. This does not include package information. To include package information, add \`?includePackages=1\` to the URL.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories":{"get":{"description":"Gets all categories from a webstore. This does not include package information. To include package information, add `?includePackages=1` to the URL.","operationId":"getCategories","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Get all categories","tags":["Headless"]}}},"components":{"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```


# Get Categories Include Packages

All categories with their packages can be retrieved at once if necessary.&#x20;

Provide `?includePackages=1` to return all package data with each **Category** object as an all-in-one request.

## Gets all categories and packages

> Gets all categories from a webstore including packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories?includePackages=1":{"get":{"description":"Gets all categories from a webstore including packages.","operationId":"getCategoriesIncludePackages","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Gets all categories and packages","tags":["Headless"]}}},"components":{"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```


# Get Category

Retrieve a specific category by providing the category ID. A list of categories and their IDs is returned by [Get Categories](/developers/headless-api/guides/categories/get-categories).

## Get specific category

> Gets information about a category and returns the packages in that category.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories/{categoryId}":{"get":{"description":"Gets information about a category and returns the packages in that category.","operationId":"getCategory","parameters":[{"description":"The ID or slug of the category to fetch.","explode":false,"in":"path","name":"categoryId","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleCategoryResponse"}}},"description":"Successful response returns the category without package information."}},"summary":"Get specific category","tags":["Headless"]}}},"components":{"schemas":{"SingleCategoryResponse":{"properties":{"data":{"$ref":"#/components/schemas/Category"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```


# Get Category Include Packages

To include all packages with a specific category, add `?includePackages=1` to your request:

## Get a category with all packages

> Gets information about a category and returns the packages in that category.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories/{categoryId}?includePackages=1":{"get":{"description":"Gets information about a category and returns the packages in that category.","operationId":"getCategoryIncludePackages","parameters":[{"description":"The ID or slug of the category to fetch.","explode":false,"in":"path","name":"categoryId","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleCategoryResponse"}}},"description":"Successful response returns the category with package information."}},"summary":"Get a category with all packages","tags":["Headless"]}}},"components":{"schemas":{"SingleCategoryResponse":{"properties":{"data":{"$ref":"#/components/schemas/Category"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```


# Coupons


# Apply Coupon

You can define Coupons in your store as discount codes for users to enter at checkout.

{% hint style="info" %}
Multiple coupons can be applied if enabled by the store. The `/remove` endpoints require specifying which coupon to remove.
{% endhint %}

## Apply a coupon

> Applies a coupon to a basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/coupons":{"post":{"description":"Applies a coupon to a basket.","operationId":"applyCoupon","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCouponRequest"}}},"description":"Provide a `coupon_code` to apply to the basket."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyCoupon_200_response"}}},"description":"Successful response returns a success message."}},"summary":"Apply a coupon","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"ApplyCouponRequest":{"properties":{"coupon_code":{"type":"string"}}},"applyCoupon_200_response":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}}
```


# Remove Coupon

To remove a coupon, provide the `coupon_code` of the coupon that was used.&#x20;

## Remove a coupon from the basket.

> Removes a coupon code from a basket

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/coupons/remove":{"post":{"description":"Removes a coupon code from a basket","operationId":"removeCoupon","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCouponRequest"}}},"description":"Provide a `coupon_code` to remove from the basket."},"responses":{"200":{"description":"Successful response."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Remove a coupon from the basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"ApplyCouponRequest":{"properties":{"coupon_code":{"type":"string"}}}}}}
```


# Checkout

When the user is ready to checkout, direct the user to the basket's  `links.checkout` URL. This is part of the BasketLinks object.

The user will enter their payment information on a secure Tebex-hosted website and complete the checkout.

If you'd like the user to stay on your site during checkout, use [Tebex.js](/developers/tebex.js/overview) alongside the Headless API.

{% hint style="warning" %}
For most stores, authorizing the user against the basket is required before checkout.&#x20;

You can do this by directing the user to the appropriate link provided by the **/baskets/auth** endpoint. See [Authorize a Basket](/developers/headless-api/guides/baskets/authorize-a-basket)
{% endhint %}

## The BasketLinks object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```


# Creator Codes


# Apply Creator Code

See [Creator Codes](https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes) in our Creators documentation for an in-depth guide on Creator Codes. These are used to attribute purchases to influencers. These codes can optionally apply a customer discount when used.

## Apply a creator code

> Applies a creator code to a basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/creator-codes":{"post":{"description":"Applies a creator code to a basket.","operationId":"applyCreatorCode","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyCreatorCode_request"}}},"description":"Provide a `creator_code` to apply to the basket."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyCreatorCode_200_response"}}},"description":"Successful response returns a success object"},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Apply a creator code","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"applyCreatorCode_request":{"properties":{"creator_code":{"type":"string"}}},"applyCreatorCode_200_response":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}}
```


# Remove Creator Code

To remove a creator code you will send a POST with no content to the `/remove` endpoint.

## Removes the creator code from the basket.

> Removes the creator code from the basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/creator-codes/remove":{"post":{"description":"Removes the creator code from the basket.","operationId":"removeCreatorCode","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"description":"Creator code removed successfully."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Removes the creator code from the basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}}}}
```


# Gift Cards


# Apply Gift Card

Gift cards enable customers to reduce or fully pay for their basket's balance at checkout.&#x20;

A gift card is a sequence of 4 groups of 4 numbers each, ex. `0127 0244 7210 1111`. Each gift card is fully unique for your store.

## Apply a gift card

> Applies a gift card to the basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/giftcards":{"post":{"description":"Applies a gift card to the basket.","operationId":"applyGiftCard","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCard"}}},"description":"Provide a `card_number` to apply to the basket."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyGiftCard_200_response"}}},"description":"Successful response returns a success message."}},"summary":"Apply a gift card","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"GiftCard":{"properties":{"card_number":{"type":"string"}}},"applyGiftCard_200_response":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}}
```


# Remove Gift Card

To remove a gift card, provide the `card_number` to remove.&#x20;

## Remove a gift card from the basket.

> Removes a gift card from the basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/giftcards/remove":{"post":{"description":"Removes a gift card from the basket.","operationId":"removeGiftCard","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/removeGiftCard_request"}}},"description":"Provide the `card_number` to remove from the basket."},"responses":{"200":{"description":"Gift card removed successfully."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Remove a gift card from the basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"removeGiftCard_request":{"properties":{"card_number":{"type":"string"}}}}}}
```


# Packages


# Get Packages

You can retrieve all packages in the store (category not required) with one endpoint.&#x20;

If the package is in a category, the category's `id` and `name`  will be provided with the package info.

## Get all packages

> Gets all packages from a webstore.\
> \
> Note: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with \`includePackages=1\` and \`basketIdent\` to fetch dynamic packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/packages":{"get":{"description":"Gets all packages from a webstore.\n\nNote: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with `includePackages=1` and `basketIdent` to fetch dynamic packages.","operationId":"getAllPackages","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."}},"summary":"Get all packages","tags":["Headless"]}}},"components":{"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```


# Get Package

A specific package's information can be retrieved at any time with the `packageId` .

## Get package

> Gets a package from a webstore by its \`ident\` or numeric ID.\
> \
> \- Using \`ident\` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\
> \- \`id\` stays numeric for standard packages. For external packages \`id\` is synthetic, so always use \`ident\`.\
> \
> Note: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with \`includePackages=1\` and \`basketIdent\` to fetch dynamic packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/packages/{packageId}":{"get":{"description":"Gets a package from a webstore by its `ident` or numeric ID.\n\n- Using `ident` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\n- `id` stays numeric for standard packages. For external packages `id` is synthetic, so always use `ident`.\n\nNote: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with `includePackages=1` and `basketIdent` to fetch dynamic packages.","operationId":"getPackage","parameters":[{"description":"The package's `ident` (recommended, e.g. `pkg_12_456`) or numeric ID.","explode":false,"in":"path","name":"packageId","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SinglePackageResponse"}}},"description":"Successful response returns the package information."}},"summary":"Get package","tags":["Headless"]}}},"components":{"schemas":{"SinglePackageResponse":{"properties":{"data":{"$ref":"#/components/schemas/Package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```

## Get packages available for basket

> Gets all packages available to the provided basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/packages?basketIdent={basketIdent}":{"get":{"description":"Gets all packages available to the provided basket.","operationId":"getPackagesForBasket","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."},"422":{"description":"The provided request is invalid."}},"summary":"Get packages available for basket","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```

## Get packages

> Gets all packages from a webstore.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}},"paths":{"/packages?ipAddress={ipAddress}":{"get":{"description":"Gets all packages from a webstore.","operationId":"getAllPackagesWithAuthedIP","parameters":[{"description":"An IP address can be provided with authenticated requests","explode":false,"in":"path","name":"ipAddress","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."},"422":{"description":"The provided request is invalid."}},"summary":"Get packages","tags":["Headless"]}}}}
```

## Get packages available for IP and basket

> Gets all packages from a webstore.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}},"paths":{"/packages?ipAddress={ipAddress}&basketIdent={basketIdent}":{"get":{"description":"Gets all packages from a webstore.","operationId":"getAllPackagesWithAuthedIPAndBasket","parameters":[{"$ref":"#/components/parameters/basketIdent"},{"description":"An IP address can be provided with authenticated requests.","explode":false,"in":"path","name":"ipAddress","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."},"422":{"description":"The provided request is invalid."}},"summary":"Get packages available for IP and basket","tags":["Headless"]}}}}
```


# Dynamic Packages

Build custom packages and personalised bundles at the moment of checkout

Dynamic packages are custom packages that you create for one basket at checkout time, with your own name and price.&#x20;

Use them for things a fixed catalogue can't cover, such as a personalised bundle or a price calculated for a specific customer.

Each dynamic package belongs to a single basket.

### Before you start

You need:

* **A dynamic category.** Create a category in the creator panel and set its type to `dynamic`. Dynamic packages can only be created in a dynamic category.
* **Basic auth credentials** to create packages. The username is your webstore identifier and the password is your API key. Keep these on your server; never send them to the browser.
* **A basket.** Dynamic packages are created for an existing basket. You'll usually create them once the customer has logged in, for example in response to the `basket.authenticated` webhook.

### How it works

1. Create the dynamic packages for the basket.
2. Fetch the dynamic category with the basket to get each package's `ident`.
3. Add the package to the basket using its `ident`.

#### 1. Create the dynamic packages

```http
PUT https://headless.tebex.io/api/accounts/{token}/baskets/{basketIdent}/dynamic-packages
Authorization: Basic {base64(webstoreIdentifier:checkoutApiKey)}
Content-Type: application/json
```

```json
{
  "basket_id": "{basketIdent}",
  "username": "Notch",
  "category_id": 34,
  "packages": [
    {
      "name": "Custom Pack",
      "price": 4.99,
      "slug": "custom-pack",
      "description": "A pack built just for you.",
      "image_url": "https://example.com/custom-pack.png",
      "custom": { "tier": "gold" }
    }
  ]
}
```

| Field                    | Required | Description                                                           |
| ------------------------ | -------- | --------------------------------------------------------------------- |
| `basket_id`              | Yes      | The basket's ident. Use the same value as `{basketIdent}` in the URL. |
| `username`               | Yes      | The username of the customer the packages are for.                    |
| `category_id`            | Yes      | The ID of your dynamic category.                                      |
| `packages`               | Yes      | The packages to create.                                               |
| `packages[].name`        | Yes      | The package name shown to the customer.                               |
| `packages[].price`       | Yes      | The package price.                                                    |
| `packages[].slug`        | Yes      | A URL-friendly identifier for the package.                            |
| `packages[].description` | No       | The package description.                                              |
| `packages[].image_url`   | No       | A URL for the package image.                                          |
| `packages[].custom`      | No       | Your own key/value string data to store with the package.             |

A successful request returns:

```json
{
  "message": "Dynamic packages updated successfully."
}
```

#### 2. Get the package idents

Fetch the dynamic category with `includePackages=1` and the basket's ident:

```http
GET https://headless.tebex.io/api/accounts/{token}/categories/34?includePackages=1&basketIdent={basketIdent}
```

```json
{
  "data": {
    "id": 34,
    "name": "Your Custom Packs",
    "dynamic": true,
    "packages": [
      {
        "id": 10,
        "ident": "dyn_34_10",
        "name": "Custom Pack",
        "base_price": 4.99,
        ...
      }
    ]
  }
}
```

{% hint style="info" %}
A dynamic category is always empty unless you pass `basketIdent`, because its packages belong to a basket. The same applies to `GET /categories?includePackages=1`.
{% endhint %}

#### 3. Add the package to the basket

Use the package's `ident` as `package_id`:

```http
POST https://headless.tebex.io/api/baskets/{basketIdent}/packages
```

```json
{
  "package_id": "dyn_34_10",
  "quantity": 1
}
```

You can use the same ident to remove the package or change its quantity, just like a standard package.

### Errors

Creating dynamic packages returns `422` with details when:

| Cause                                  | Message                                             |
| -------------------------------------- | --------------------------------------------------- |
| Basic auth credentials are missing     | `Basic auth credentials are required`               |
| `basket_id` is missing                 | `The basket id field is required.`                  |
| `basket_id` isn't a string             | `The basket id field must be a string.`             |
| `category_id` isn't a dynamic category | `The specified category is not a dynamic category.` |


# Pages


# Get Custom Pages

Gets a list of **custom pages** associated with the webstore. These contain a `content` variable with the HTML content of the page.

## Get custom pages defined for the webstore.

> Gets a list of custom pages associated with the webstore. These contain a \`content\` variable with the HTML content of the page.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/pages":{"get":{"description":"Gets a list of custom pages associated with the webstore. These contain a `content` variable with the HTML content of the page.","operationId":"getCustomPages","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CMSPagesResponse"}}},"description":"Successful response returns the webstore's pages."}},"summary":"Get custom pages defined for the webstore.","tags":["Headless"]}}},"components":{"schemas":{"CMSPagesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CMSPage"},"type":"array"}}},"CMSPage":{"properties":{"id":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"account_id":{"type":"integer"},"title":{"type":"string"},"slug":{"type":"string"},"private":{"type":"boolean"},"hidden":{"type":"boolean"},"disabled":{"type":"boolean"},"sequence":{"type":"boolean"},"content":{"type":"string"}}}}}}
```


# Sidebar


# Get Sidebar Modules

Stores can enable modules that showcase specific data about the store. More information on the available modules can be found in our Creator Docs: [Sidebar](https://docs.tebex.io/creators/tebex-control-panel/webstore/sidebar)

## Retrieves the available sidebar modules.

> Retrieves the available sidebar modules configured for the store.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/sidebar":{"get":{"description":"Retrieves the available sidebar modules configured for the store.","operationId":"getSidebar","parameters":[{"description":"The webstore identifier.","explode":false,"in":"path","name":"token","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModulesResponse"}}},"description":"Successful response."}},"summary":"Retrieves the available sidebar modules.","tags":["Headless"]}}},"components":{"schemas":{"ModulesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Module"},"type":"array"}},"required":["data"]},"Module":{"discriminator":{"mapping":{"top_customer":"#/components/schemas/TopCustomerModule","textbox":"#/components/schemas/TextboxModule","recent_payments":"#/components/schemas/RecentPaymentsModule","featured_package":"#/components/schemas/FeaturedPackageModule","giftcard_balance":"#/components/schemas/GiftcardBalanceModule","server_status":"#/components/schemas/ServerStatusModule","payment_goal":"#/components/schemas/PaymentGoalModule","community_goal":"#/components/schemas/CommunityGoalModule"},"propertyName":"type"},"oneOf":[{"$ref":"#/components/schemas/TopCustomerModule"},{"$ref":"#/components/schemas/TextboxModule"},{"$ref":"#/components/schemas/RecentPaymentsModule"},{"$ref":"#/components/schemas/FeaturedPackageModule"},{"$ref":"#/components/schemas/GiftcardBalanceModule"},{"$ref":"#/components/schemas/ServerStatusModule"},{"$ref":"#/components/schemas/PaymentGoalModule"},{"$ref":"#/components/schemas/CommunityGoalModule"}]},"TopCustomerModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/TopCustomerData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"TopCustomerData":{"properties":{"header":{"type":"string"},"username":{"type":"string"},"username_id":{"description":"User identifier.","type":"string"},"total":{"description":"Optional, present depending on module configuration.","type":"number"}},"required":["header","username","username_id"]},"TextboxModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/TextboxData"}},"required":["data"]}]},"TextboxData":{"properties":{"header":{"type":"string"},"text":{"description":"HTML supported.","type":"string"}},"required":["header","text"]},"RecentPaymentsModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/RecentPaymentsData"}},"required":["data"]}]},"RecentPaymentsData":{"properties":{"header":{"type":"string"},"payments":{"items":{"$ref":"#/components/schemas/RecentPayment"},"type":"array"}},"required":["header","payments"]},"RecentPayment":{"properties":{"username":{"type":"string"},"username_id":{"type":"string"},"package":{"$ref":"#/components/schemas/RecentPayment_package"},"created_at":{"description":"Optional, present depending on module configuration.","format":"date-time","nullable":true,"type":"string"},"price":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"currency":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"string"}},"required":["package","username","username_id"]},"RecentPayment_package":{"properties":{"name":{"type":"string"}},"required":["name"]},"FeaturedPackageModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/FeaturedPackageData"}},"required":["data"]}]},"FeaturedPackageData":{"properties":{"header":{"type":"string"},"package":{"$ref":"#/components/schemas/Package"}},"required":["header","package"]},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"GiftcardBalanceModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/GiftcardBalanceData"}},"required":["data"]}]},"GiftcardBalanceData":{"properties":{"header":{"type":"string"}},"required":["header"]},"ServerStatusModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/ServerStatusData"}},"required":["data"]}]},"ServerStatusData":{"properties":{"header":{"type":"string"},"hostname":{"type":"string"},"port":{"type":"integer"},"online":{"type":"boolean"},"players":{"$ref":"#/components/schemas/Players"}},"required":["header","hostname","online","players","port"]},"Players":{"properties":{"online":{"type":"integer"},"max":{"type":"integer"}},"required":["max","online"]},"PaymentGoalModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/PaymentGoalData"}},"required":["data"]}]},"PaymentGoalData":{"properties":{"header":{"type":"string"},"percentage":{"maximum":100,"minimum":0,"type":"number"},"bar_style":{"enum":["normal","striped"],"type":"string"},"bar_animated":{"type":"boolean"},"total":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"target":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"}},"required":["bar_animated","bar_style","header","percentage"]},"CommunityGoalModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/CommunityGoalData"}},"required":["data"]}]},"CommunityGoalData":{"properties":{"header":{"type":"string"},"bar_style":{"enum":["normal","striped"],"type":"string"},"bar_animated":{"type":"boolean"},"percentage":{"maximum":100,"minimum":0,"type":"number"},"total_payments":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"target":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"times_achieved":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"integer"}},"required":["bar_animated","bar_style","header","percentage"]}}}}
```

### Sidebar Module Types

Below are the available sidebar modules and their definitions:

| Type               | Notes                                   |
| ------------------ | --------------------------------------- |
| `top_customer`     | Shows the top customer of the store.    |
| `textbox`          | Renders custom HTML on the sidebar      |
| `recent_payments`  | Shows information of most recent payor  |
| `featured_package` | Showcases a particular package          |
| `giftcard_balance` | Shows the user's giftcard balance       |
| `server_status`    | Online status of a store's server       |
| `payment_goal`     | Progress to completing a payment goal   |
| `community_goal`   | Progress to completing a community goal |

## The TextboxModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"TextboxModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/TextboxData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"TextboxData":{"properties":{"header":{"type":"string"},"text":{"description":"HTML supported.","type":"string"}},"required":["header","text"]}}}}
```

## The TopCustomerModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"TopCustomerModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/TopCustomerData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"TopCustomerData":{"properties":{"header":{"type":"string"},"username":{"type":"string"},"username_id":{"description":"User identifier.","type":"string"},"total":{"description":"Optional, present depending on module configuration.","type":"number"}},"required":["header","username","username_id"]}}}}
```

## The PaymentGoalModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"PaymentGoalModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/PaymentGoalData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"PaymentGoalData":{"properties":{"header":{"type":"string"},"percentage":{"maximum":100,"minimum":0,"type":"number"},"bar_style":{"enum":["normal","striped"],"type":"string"},"bar_animated":{"type":"boolean"},"total":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"target":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"}},"required":["bar_animated","bar_style","header","percentage"]}}}}
```

## The ServerStatusModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"ServerStatusModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/ServerStatusData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"ServerStatusData":{"properties":{"header":{"type":"string"},"hostname":{"type":"string"},"port":{"type":"integer"},"online":{"type":"boolean"},"players":{"$ref":"#/components/schemas/Players"}},"required":["header","hostname","online","players","port"]},"Players":{"properties":{"online":{"type":"integer"},"max":{"type":"integer"}},"required":["max","online"]}}}}
```

## The CommunityGoalModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"CommunityGoalModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/CommunityGoalData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"CommunityGoalData":{"properties":{"header":{"type":"string"},"bar_style":{"enum":["normal","striped"],"type":"string"},"bar_animated":{"type":"boolean"},"percentage":{"maximum":100,"minimum":0,"type":"number"},"total_payments":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"target":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"times_achieved":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"integer"}},"required":["bar_animated","bar_style","header","percentage"]}}}}
```

## The RecentPaymentsModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"RecentPaymentsModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/RecentPaymentsData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"RecentPaymentsData":{"properties":{"header":{"type":"string"},"payments":{"items":{"$ref":"#/components/schemas/RecentPayment"},"type":"array"}},"required":["header","payments"]},"RecentPayment":{"properties":{"username":{"type":"string"},"username_id":{"type":"string"},"package":{"$ref":"#/components/schemas/RecentPayment_package"},"created_at":{"description":"Optional, present depending on module configuration.","format":"date-time","nullable":true,"type":"string"},"price":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"currency":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"string"}},"required":["package","username","username_id"]},"RecentPayment_package":{"properties":{"name":{"type":"string"}},"required":["name"]}}}}
```

## The FeaturedPackageModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"FeaturedPackageModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/FeaturedPackageData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"FeaturedPackageData":{"properties":{"header":{"type":"string"},"package":{"$ref":"#/components/schemas/Package"}},"required":["header","package"]},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```

## The GiftcardBalanceModule object

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"components":{"schemas":{"GiftcardBalanceModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/GiftcardBalanceData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"GiftcardBalanceData":{"properties":{"header":{"type":"string"}},"required":["header"]}}}}
```


# Tiers

This guide will detail the expected flows and endpoints for implementing tiers using Headless API.&#x20;

See our Creator docs for[ Tiered Packages](https://docs.tebex.io/creators/tebex-control-panel/how-to-create-packages/tiered-packages) to learn how to set up tiers.

{% hint style="info" %}
If you are using an older or custom store template, you may need to modify your template to support tiers. A tiered category view is different from a non-tiered category.

See [Supporting Tiers on Custom Store Templates](/developers/templates/guides/supporting-tiers-on-custom-store-templates) to learn how to set up the necessary pages.
{% endhint %}

## Checkout Flow

Tiers require an authenticated user. After you create the basket, you must log the user in using the relevant basket auth links.

See [Creating A Basket](broken://pages/CZJQOggrYhfA81mhR8YU) for further information.

The expected flow for checking out with a Tier is identical to any other package:

1. Create the basket
2. Authenticate the user via the basket's auth links
3. Add the tiered package to the basket
4. Direct the user to checkout

On successful checkout, the user will now have an `active_tier` when retrieving their tiered categories against their `usernameId`.

If the `active_tier` property is not present, the user does not have an active package in that tier.

## API Endpoints

Tiered categories use our existing `/categories` endpoint.&#x20;

{% hint style="warning" %}
Unlike other Headless API endpoints, you must use HTTP Basic authentication with the **Username** set to your **Public Token** and **Password** as your Private Key. See [Authorization](/developers/headless-api/authorization) for more information.
{% endhint %}

All tiered categories will have the property `tiered: true`&#x20;


# Get Tiered Categories

To get tiered categories, you use the same `/categories` endpoint. Categories that are tiered have a `tiered: true`  parameter.

## Get all categories

> Gets all categories from a webstore. This does not include package information. To include package information, add \`?includePackages=1\` to the URL.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories":{"get":{"description":"Gets all categories from a webstore. This does not include package information. To include package information, add `?includePackages=1` to the URL.","operationId":"getCategories","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Get all categories","tags":["Headless"]}}},"components":{"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```


# Get Active Tier

Provide a `usernameId` as a query parameter to `/categories` to check for an `active_tier` .&#x20;

{% hint style="info" %}
This will be the `usernameId` provided by the basket when created with a valid username.
{% endhint %}

```
GET /api/accounts/categories?usernameId=123456789
```

`active_tier` will be a parameter returned with the `Category` object if the user has an active tier for that category.

```json
"active_tier": {
    "id": 40796,
    "created_at": "2025-05-14T13:48:56.000000Z",
    "username_id": "text",
    "package": {
      "id": 6276316,
      "name": "test package 101",
      "description": "<p>this is just a test. only a test. nothing more.</p>",
      "image": null,
      "type": "single",
      "category": {
        "id": 2678660,
        "name": "Packages"
      },
      "base_price": 5,
      "sales_tax": 0,
      "total_price": 5,
      "currency": "USD",
      "prorate_price": 1,
      "discount": 0,
      "disable_quantity": false,
      "disable_gifting": false,
      "expiration_date": null,
      "media": [],
      "order": 1,
      "slug": "text",
      "user_limit": 1,
      "creator_meta_data": {},
      "options": [],
      "variables": [],
      "created_at": "2024-05-21T18:09:17+00:00",
      "updated_at": "2024-05-21T18:09:17+00:00"
    },
    "active": true,
    "recurring_payment_reference": "tbx-r-757925142",
    "next_payment_date": "2025-06-14T13:48:56+00:00",
    "status": {
      "id": 2,
      "description": "Active"
    },
    "pending_downgrade_package": {
      "id": 6834820,
      "name": "Bronze"
    }
  },
  "description": "text",
  "packages": [
    {
      "id": 6276316,
      "name": "test package 101",
      "description": "<p>this is just a test. only a test. nothing more.</p>",
      "image": null,
      "type": "single",
      "category": {
        "id": 2678660,
        "name": "Packages"
      },
      "base_price": 5,
      "sales_tax": 0,
      "total_price": 5,
      "currency": "USD",
      "prorate_price": 1,
      "discount": 0,
      "disable_quantity": false,
      "disable_gifting": false,
      "expiration_date": null,
      "media": [],
      "order": 1,
      "slug": "text",
      "user_limit": 1,
      "creator_meta_data": {},
      "options": [],
      "variables": [],
      "created_at": "2024-05-21T18:09:17+00:00",
      "updated_at": "2024-05-21T18:09:17+00:00"
    }
  ],
  "order": 1,
  "display_type": "list",
  "image_url": null,
  "dynamic": false
}
```


# Update Tier

This will change a user's tier immediately to the new package you specify. If payment is required, it will automatically be processed.

{% hint style="info" %}
A **recurring\_payment\_updated** webhook is sent when an update is successful.
{% endhint %}

{% hint style="danger" %}
This endpoint must be enabled for your store by Tebex. Please contact your Creator Success Manager or our support team to begin the process.
{% endhint %}

## Update user's tier to a new package

> Updates a tier to a new package. A recurring payment updated webhook is sent when an update is successful.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"updateTier_request":{"properties":{"package_id":{"type":"integer"}}},"UpdateTierResponse":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}},"paths":{"/tiers/{tierId}":{"patch":{"description":"Updates a tier to a new package. A recurring payment updated webhook is sent when an update is successful.","operationId":"updateTier","parameters":[{"description":"The tier identifier","explode":false,"in":"path","name":"tierId","required":true,"schema":{"type":"integer"},"style":"simple"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateTier_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTierResponse"}}},"description":"Successful response."}},"summary":"Update user's tier to a new package","tags":["Headless"]}}}}
```


# Endpoints

All endpoints for Headless API: for specific implementation guides see Guides

## Get the webstore's information

> Gets the webstore associated with the provided token

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/":{"get":{"description":"Gets the webstore associated with the provided token","operationId":"getWebstore","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebstoreResponse"}}},"description":"Successful response returns the webstore's information."}},"summary":"Get the webstore's information","tags":["Headless"]}}},"components":{"schemas":{"WebstoreResponse":{"description":"Wrapped webstore information in a \"data\" object.","properties":{"data":{"$ref":"#/components/schemas/Webstore"}}},"Webstore":{"properties":{"id":{"type":"integer"},"description":{"description":"Store description in HTML format","type":"string"},"name":{"description":"Name of the store","type":"string"},"webstore_url":{"description":"URL of the webstore","format":"uri","type":"string"},"currency":{"description":"Currency used in the store","type":"string"},"lang":{"description":"Language of the store","type":"string"},"logo":{"description":"URL of the store's logo","format":"uri","type":"string","nullable":true},"platform_type":{"description":"Platform type for the store","type":"string"},"platform_type_id":{"type":"string"},"disabled":{"description":"True if the store is disabled.","type":"boolean"},"created_at":{"description":"The date and time when the store was created","format":"date-time","type":"string"},"supports_usernames":{"description":"True if the store's platform identifies customers by username.","type":"boolean"},"supports_gifting":{"description":"True if packages can be gifted to another user.","type":"boolean"}}}}}}
```

## Get custom pages defined for the webstore.

> Gets a list of custom pages associated with the webstore. These contain a \`content\` variable with the HTML content of the page.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/pages":{"get":{"description":"Gets a list of custom pages associated with the webstore. These contain a `content` variable with the HTML content of the page.","operationId":"getCustomPages","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CMSPagesResponse"}}},"description":"Successful response returns the webstore's pages."}},"summary":"Get custom pages defined for the webstore.","tags":["Headless"]}}},"components":{"schemas":{"CMSPagesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CMSPage"},"type":"array"}}},"CMSPage":{"properties":{"id":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"account_id":{"type":"integer"},"title":{"type":"string"},"slug":{"type":"string"},"private":{"type":"boolean"},"hidden":{"type":"boolean"},"disabled":{"type":"boolean"},"sequence":{"type":"boolean"},"content":{"type":"string"}}}}}}
```

## Get a basket

> Gets a basket associated with the provided identifier.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}":{"get":{"description":"Gets a basket associated with the provided identifier.","operationId":"getBasket","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response returns the basket information."}},"summary":"Get a basket","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```

## Create a new basket

> Creates a new basket for use during checkout.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets":{"post":{"description":"Creates a new basket for use during checkout.","operationId":"createBasket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/createBasket_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response returns the basket information."},"422":{"description":"The provided webstore ID is invalid."}},"summary":"Create a new basket","tags":["Headless"]}}},"components":{"schemas":{"createBasket_request":{"properties":{"complete_url":{"description":"A URL the user can return to when checkout is completed.","type":"string"},"cancel_url":{"description":"A URL the user can return to when cancelling checkout.","type":"string"},"custom":{"description":"Custom data you wish to associate with the basket. This data will be included with webhook responses and GET requests associated with the Basket.","type":"object"},"complete_auto_redirect":{"description":"True if the user should automatically be redirected to the relevant complete/cancel URL","type":"boolean"}}},"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```

## Get auth links for basket

> Fetches a basket's auth URL. The player should be directed here in order for them to authorize their account.\
> When complete, they will be returned to the provided \`returnUrl\` and the basket will be authorized from that moment onwards.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/auth?returnUrl={returnUrl}":{"get":{"description":"Fetches a basket's auth URL. The player should be directed here in order for them to authorize their account.\nWhen complete, they will be returned to the provided `returnUrl` and the basket will be authorized from that moment onwards.","operationId":"getBasketAuthUrl","parameters":[{"$ref":"#/components/parameters/basketIdent"},{"description":"The URL you would like to redirect the user to after successful basket authentication.","explode":false,"in":"path","name":"returnUrl","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketAuthResponse"}}},"description":"Successful response returns the auth provider options and URLs of the sign-in link."},"422":{"description":"The provided webstore ID or basket ID is invalid."}},"summary":"Get auth links for basket","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"BasketAuthResponse":{"items":{"$ref":"#/components/schemas/BasketAuthResponse_inner"},"type":"array"},"BasketAuthResponse_inner":{"properties":{"name":{"type":"string"},"url":{"type":"string"}}}}}}
```

## Add packages to a dynamic category for a basket.

> Populates a dynamic category with custom packages for the given basket. Dynamic categories are created in the creator panel with the type \`dynamic\`, and are typically populated in response to a \`basket.authenticated\` webhook.\
> \
> Requires basic auth: the username is the webstore identifier and the password is the account's checkout API key.\
> \
> Once created, the packages can be fetched using the category endpoints with both \`includePackages=1\` and \`basketIdent\` provided.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"DynamicPackagesRequest":{"properties":{"basket_id":{"description":"The basket's ident. Use the same value as the `basketIdent` path parameter.","type":"string"},"username":{"description":"The username of the authenticated customer the packages are being created for.","type":"string"},"category_id":{"description":"The ID of the dynamic category to populate. Must be a category of type `dynamic`.","type":"integer"},"packages":{"items":{"$ref":"#/components/schemas/DynamicPackageInput"},"type":"array"}},"required":["basket_id","category_id","packages","username"]},"DynamicPackageInput":{"description":"A custom package to add to a dynamic category.","properties":{"name":{"type":"string"},"price":{"format":"float","type":"number"},"slug":{"type":"string"},"description":{"type":"string"},"image_url":{"type":"string"},"custom":{"additionalProperties":{"type":"string"},"description":"Arbitrary custom key/value data to associate with the package."}},"required":["name","price","slug"]},"DynamicPackagesResponse":{"properties":{"message":{"type":"string"}}},"ErrorResponse":{"properties":{"type":{},"title":{"description":"A short, human-readable summary of the problem type.  It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization","type":"string"},"status":{"description":"The HTTP status code gen by the origin server for the occurrence of the problem.","type":"integer"},"detail":{"description":"A human-readable explanation specific to this occurrence of the problem.","type":"string"},"instance":{"description":"A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced","type":"string"}}}}},"paths":{"/baskets/{basketIdent}/dynamic-packages":{"put":{"description":"Populates a dynamic category with custom packages for the given basket. Dynamic categories are created in the creator panel with the type `dynamic`, and are typically populated in response to a `basket.authenticated` webhook.\n\nRequires basic auth: the username is the webstore identifier and the password is the account's checkout API key.\n\nOnce created, the packages can be fetched using the category endpoints with both `includePackages=1` and `basketIdent` provided.","operationId":"createDynamicPackage","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicPackagesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicPackagesResponse"}}},"description":"Successful response confirms the dynamic packages were created."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The request is invalid. The error response will include detail as to which parameter failed validation. This is also returned when basic auth credentials are missing (\"Basic auth credentials are required\") or when `category_id` is not a dynamic category (\"The specified category is not a dynamic category.\")."}},"summary":"Add packages to a dynamic category for a basket.","tags":["Headless"]}}}}
```

## Get all categories

> Gets all categories from a webstore. This does not include package information. To include package information, add \`?includePackages=1\` to the URL.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories":{"get":{"description":"Gets all categories from a webstore. This does not include package information. To include package information, add `?includePackages=1` to the URL.","operationId":"getCategories","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Get all categories","tags":["Headless"]}}},"components":{"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```

## Gets all categories and packages

> Gets all categories from a webstore including packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories?includePackages=1":{"get":{"description":"Gets all categories from a webstore including packages.","operationId":"getCategoriesIncludePackages","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Gets all categories and packages","tags":["Headless"]}}},"components":{"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```

## Get user's tiered categories

> Gets all categories from the webstore, returning active tier information for the given player.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}},"paths":{"/categories?usernameId={usernameId}&includePackages=1":{"get":{"description":"Gets all categories from the webstore, returning active tier information for the given player.","operationId":"getUserTieredCategories","parameters":[{"explode":false,"in":"path","name":"usernameId","required":true,"schema":{"type":"integer"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Get user's tiered categories","tags":["Headless"]}}}}
```

## Get Dynamic Categories

> Gets all categories from a webstore including packages. When \`basketIdent\` is provided, dynamic categories are populated with the packages associated with that basket.\
> \
> If a basket identifier is not provided, dynamic categories will be empty as the basket is required to relate packages to the category.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories?includePackages=1&basketIdent={basketIdent}":{"get":{"description":"Gets all categories from a webstore including packages. When `basketIdent` is provided, dynamic categories are populated with the packages associated with that basket.\n\nIf a basket identifier is not provided, dynamic categories will be empty as the basket is required to relate packages to the category.","operationId":"getDynamicCategories","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}},"description":"Successful response returns a list of category information."}},"summary":"Get Dynamic Categories","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"CategoryResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Category"},"type":"array"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```

## Get specific category

> Gets information about a category and returns the packages in that category.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories/{categoryId}":{"get":{"description":"Gets information about a category and returns the packages in that category.","operationId":"getCategory","parameters":[{"description":"The ID or slug of the category to fetch.","explode":false,"in":"path","name":"categoryId","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleCategoryResponse"}}},"description":"Successful response returns the category without package information."}},"summary":"Get specific category","tags":["Headless"]}}},"components":{"schemas":{"SingleCategoryResponse":{"properties":{"data":{"$ref":"#/components/schemas/Category"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```

## Get a category with all packages

> Gets information about a category and returns the packages in that category.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories/{categoryId}?includePackages=1":{"get":{"description":"Gets information about a category and returns the packages in that category.","operationId":"getCategoryIncludePackages","parameters":[{"description":"The ID or slug of the category to fetch.","explode":false,"in":"path","name":"categoryId","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleCategoryResponse"}}},"description":"Successful response returns the category with package information."}},"summary":"Get a category with all packages","tags":["Headless"]}}},"components":{"schemas":{"SingleCategoryResponse":{"properties":{"data":{"$ref":"#/components/schemas/Category"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```

## Gets a specific category including packages, populating a dynamic category for the given basket.

> Gets information about a category and returns the packages in that category. When the category is dynamic and \`basketIdent\` is provided, the category is populated with the packages associated with that basket.\
> \
> If a basket identifier is not provided, a dynamic category will be empty as the basket is required to relate packages to the category.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/categories/{categoryId}?includePackages=1&basketIdent={basketIdent}":{"get":{"description":"Gets information about a category and returns the packages in that category. When the category is dynamic and `basketIdent` is provided, the category is populated with the packages associated with that basket.\n\nIf a basket identifier is not provided, a dynamic category will be empty as the basket is required to relate packages to the category.","operationId":"getCategoryIncludeDynamicPackages","parameters":[{"description":"The ID or slug of the category to fetch.","explode":false,"in":"path","name":"categoryId","required":true,"schema":{"type":"string"},"style":"simple"},{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SingleCategoryResponse"}}},"description":"Successful response returns the category with package information."}},"summary":"Gets a specific category including packages, populating a dynamic category for the given basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"SingleCategoryResponse":{"properties":{"data":{"$ref":"#/components/schemas/Category"}}},"Category":{"properties":{"id":{"type":"integer"},"name":{"description":"User-friendly name of the category","type":"string"},"slug":{"description":"Short identifier slug for the category","type":"string","nullable":true},"parent":{"description":"Parent category, if applicable","format":"Category","type":"object","nullable":true},"tiered":{"description":"True if this is a tiered category","type":"boolean"},"active_tier":{"$ref":"#/components/schemas/Tier"},"description":{"description":"HTML description of the category","type":"string"},"packages":{"description":"Packages within the category. For dynamic categories, packages use the `DynamicPackage` shape and are only populated when a `basketIdent` is provided.","items":{"$ref":"#/components/schemas/Package"},"type":"array","nullable":true},"order":{"description":"The numeric order in which to display the category.","type":"integer"},"display_type":{"description":"How the category should be displayed","enum":["list","grid"],"type":"string"},"image_url":{"description":"URL of the category image, if set.","format":"uri","type":"string","nullable":true},"dynamic":{"description":"True if this is a dynamic category. Dynamic categories are populated with custom packages per-basket using the Add Dynamic Packages endpoint, and their packages can only be fetched by providing a `basketIdent`.","type":"boolean"}}},"Tier":{"properties":{"id":{"type":"integer"},"created_at":{"description":"The date and time when the tier became active","format":"date-time","type":"string"},"username_id":{"description":"The user's username ID. For Steam, this is a numeric representation of their Steam64ID","type":"string"},"package":{"$ref":"#/components/schemas/Package"},"active":{"description":"True if the tier is currently active.","type":"boolean"},"recurring_payment_reference":{"description":"The ID of the recurring payment this tier is attached to.","type":"string"},"next_payment_date":{"description":"The date and time of the next payment for this tier.","format":"date-time","type":"string"},"status":{"$ref":"#/components/schemas/Tier_status"},"pending_downgrade_package":{"$ref":"#/components/schemas/Tier_pending_downgrade_package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"Tier_status":{"properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"Tier_pending_downgrade_package":{"description":"The package this tier is downgrading to if a downgrade is pending.","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"nullable":true}}}}
```

## Get package

> Gets a package from a webstore by its \`ident\` or numeric ID.\
> \
> \- Using \`ident\` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\
> \- \`id\` stays numeric for standard packages. For external packages \`id\` is synthetic, so always use \`ident\`.\
> \
> Note: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with \`includePackages=1\` and \`basketIdent\` to fetch dynamic packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/packages/{packageId}":{"get":{"description":"Gets a package from a webstore by its `ident` or numeric ID.\n\n- Using `ident` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\n- `id` stays numeric for standard packages. For external packages `id` is synthetic, so always use `ident`.\n\nNote: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with `includePackages=1` and `basketIdent` to fetch dynamic packages.","operationId":"getPackage","parameters":[{"description":"The package's `ident` (recommended, e.g. `pkg_12_456`) or numeric ID.","explode":false,"in":"path","name":"packageId","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SinglePackageResponse"}}},"description":"Successful response returns the package information."}},"summary":"Get package","tags":["Headless"]}}},"components":{"schemas":{"SinglePackageResponse":{"properties":{"data":{"$ref":"#/components/schemas/Package"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```

## Get all packages

> Gets all packages from a webstore.\
> \
> Note: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with \`includePackages=1\` and \`basketIdent\` to fetch dynamic packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/packages":{"get":{"description":"Gets all packages from a webstore.\n\nNote: this endpoint does not support packages belonging to dynamic categories. Use the category endpoints with `includePackages=1` and `basketIdent` to fetch dynamic packages.","operationId":"getAllPackages","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."}},"summary":"Get all packages","tags":["Headless"]}}},"components":{"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```

## Get packages

> Gets all packages from a webstore.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}},"paths":{"/packages?ipAddress={ipAddress}":{"get":{"description":"Gets all packages from a webstore.","operationId":"getAllPackagesWithAuthedIP","parameters":[{"description":"An IP address can be provided with authenticated requests","explode":false,"in":"path","name":"ipAddress","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."},"422":{"description":"The provided request is invalid."}},"summary":"Get packages","tags":["Headless"]}}}}
```

## Get packages available for basket

> Gets all packages available to the provided basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/packages?basketIdent={basketIdent}":{"get":{"description":"Gets all packages available to the provided basket.","operationId":"getPackagesForBasket","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."},"422":{"description":"The provided request is invalid."}},"summary":"Get packages available for basket","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}}}
```

## Get packages available for IP and basket

> Gets all packages from a webstore.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"PackageResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Package"},"type":"array"}}},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}}}},"paths":{"/packages?ipAddress={ipAddress}&basketIdent={basketIdent}":{"get":{"description":"Gets all packages from a webstore.","operationId":"getAllPackagesWithAuthedIPAndBasket","parameters":[{"$ref":"#/components/parameters/basketIdent"},{"description":"An IP address can be provided with authenticated requests.","explode":false,"in":"path","name":"ipAddress","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageResponse"}}},"description":"Successful response returns a list of package information."},"422":{"description":"The provided request is invalid."}},"summary":"Get packages available for IP and basket","tags":["Headless"]}}}}
```

## Apply a creator code

> Applies a creator code to a basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/creator-codes":{"post":{"description":"Applies a creator code to a basket.","operationId":"applyCreatorCode","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyCreatorCode_request"}}},"description":"Provide a `creator_code` to apply to the basket."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyCreatorCode_200_response"}}},"description":"Successful response returns a success object"},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Apply a creator code","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"applyCreatorCode_request":{"properties":{"creator_code":{"type":"string"}}},"applyCreatorCode_200_response":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}}
```

## Removes the creator code from the basket.

> Removes the creator code from the basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/creator-codes/remove":{"post":{"description":"Removes the creator code from the basket.","operationId":"removeCreatorCode","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"responses":{"200":{"description":"Creator code removed successfully."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Removes the creator code from the basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}}}}
```

## Apply a gift card

> Applies a gift card to the basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/giftcards":{"post":{"description":"Applies a gift card to the basket.","operationId":"applyGiftCard","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiftCard"}}},"description":"Provide a `card_number` to apply to the basket."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyGiftCard_200_response"}}},"description":"Successful response returns a success message."}},"summary":"Apply a gift card","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"GiftCard":{"properties":{"card_number":{"type":"string"}}},"applyGiftCard_200_response":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}}
```

## Remove a gift card from the basket.

> Removes a gift card from the basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/giftcards/remove":{"post":{"description":"Removes a gift card from the basket.","operationId":"removeGiftCard","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/removeGiftCard_request"}}},"description":"Provide the `card_number` to remove from the basket."},"responses":{"200":{"description":"Gift card removed successfully."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Remove a gift card from the basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"removeGiftCard_request":{"properties":{"card_number":{"type":"string"}}}}}}
```

## Apply a coupon

> Applies a coupon to a basket.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/coupons":{"post":{"description":"Applies a coupon to a basket.","operationId":"applyCoupon","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCouponRequest"}}},"description":"Provide a `coupon_code` to apply to the basket."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/applyCoupon_200_response"}}},"description":"Successful response returns a success message."}},"summary":"Apply a coupon","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"ApplyCouponRequest":{"properties":{"coupon_code":{"type":"string"}}},"applyCoupon_200_response":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}}
```

## Remove a coupon from the basket.

> Removes a coupon code from a basket

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/baskets/{basketIdent}/coupons/remove":{"post":{"description":"Removes a coupon code from a basket","operationId":"removeCoupon","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyCouponRequest"}}},"description":"Provide a `coupon_code` to remove from the basket."},"responses":{"200":{"description":"Successful response."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Remove a coupon from the basket.","tags":["Headless"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"ApplyCouponRequest":{"properties":{"coupon_code":{"type":"string"}}}}}}
```

## Add package to basket

> Add a package to the basket by its \`ident\` or numeric ID.\
> \
> \- Using \`ident\` is recommended, since it works for every package type. It is required for external packages.\
> \- Numeric IDs still work for standard packages.\
> \
> To add a package belonging to a dynamic category, set \`dynamic\` to \`true\`. Without this property the API will treat the request as a normal package ID.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Endpoints requiring only a basket ident with no token","name":"Baskets"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/{basketIdent}/packages":{"post":{"description":"Add a package to the basket by its `ident` or numeric ID.\n\n- Using `ident` is recommended, since it works for every package type. It is required for external packages.\n- Numeric IDs still work for standard packages.\n\nTo add a package belonging to a dynamic category, set `dynamic` to `true`. Without this property the API will treat the request as a normal package ID.","operationId":"addBasketPackage","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/addBasketPackage_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The ident is unknown or does not match a package in this store (\"The selected id is invalid.\")."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation. A malformed `package_id` fails with \"package_id must be a package ID or ident.\""}},"summary":"Add package to basket","tags":["Baskets"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"addBasketPackage_request":{"properties":{"package_id":{"description":"The package's `ident` (recommended) or numeric ID. `ident` is required for external packages. Send the `ident` exactly as returned by the package endpoints.","type":"string"},"quantity":{"type":"integer"},"dynamic":{"description":"Set to `true` when adding a package that belongs to a dynamic category. When omitted, the API acts as if a normal package ID was provided.","type":"boolean"}},"required":["package_id","quantity"]},"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}},"ErrorResponse":{"properties":{"type":{},"title":{"description":"A short, human-readable summary of the problem type.  It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization","type":"string"},"status":{"description":"The HTTP status code gen by the origin server for the occurrence of the problem.","type":"integer"},"detail":{"description":"A human-readable explanation specific to this occurrence of the problem.","type":"string"},"instance":{"description":"A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced","type":"string"}}}}}}
```

## Remove a package from a basket

> Remove a package from the basket by its \`ident\` or numeric ID.\
> \
> \- Using \`ident\` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\
> \- Numeric IDs still work for standard packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Endpoints requiring only a basket ident with no token","name":"Baskets"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/{basketIdent}/packages/remove":{"post":{"description":"Remove a package from the basket by its `ident` or numeric ID.\n\n- Using `ident` is recommended, since it works for every package type. Send it back exactly as returned; don't build or parse it.\n- Numeric IDs still work for standard packages.","operationId":"removeBasketPackage","parameters":[{"$ref":"#/components/parameters/basketIdent"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/removeBasketPackage_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasketResponse"}}},"description":"Successful response returns the basket."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Remove a package from a basket","tags":["Baskets"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"removeBasketPackage_request":{"properties":{"package_id":{"description":"The package's `ident` (recommended) or numeric ID.","type":"string"}}},"BasketResponse":{"properties":{"data":{"$ref":"#/components/schemas/Basket"}}},"Basket":{"properties":{"id":{"type":"string"},"ident":{"type":"string"},"complete":{"type":"boolean"},"email":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"coupons":{"items":{"$ref":"#/components/schemas/Coupon"},"type":"array"},"giftcards":{"items":{"$ref":"#/components/schemas/GiftCard"},"type":"array"},"creator_code":{"description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes","type":"string"},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"country":{"description":"A two-character country code","type":"string"},"ip":{"type":"string"},"username_id":{"type":"integer"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"description":"A 3 character currency code","type":"string"},"packages":{"items":{"$ref":"#/components/schemas/BasketPackage"},"type":"array"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"Coupon":{"properties":{"code":{"type":"string"}}},"GiftCard":{"properties":{"card_number":{"type":"string"}}},"BasketPackage":{"description":"A package within an existing basket.","properties":{"id":{"description":"The package ID","type":"integer"},"description":{"type":"string"},"image":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"in_basket":{"$ref":"#/components/schemas/BasketPackage_in_basket"},"type":{"description":"The type of payment, either `single` for one-time payments or `subscription`.","enum":["single","subscription"],"type":"string"},"revenue_share":{"description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"},"type":"array"},"is_recurring":{"description":"Whether this package is a recurring (subscription) purchase.","type":"boolean"}}},"BasketPackage_in_basket":{"properties":{"quantity":{"description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket.","type":"integer"},"price":{"format":"float","type":"number"},"gift_username_id":{"description":"The username id of the user this package is gifted to","type":"string"},"gift_username":{"description":"The username of the user this package is gifted to.","type":"string"}}},"RevenueShare":{"properties":{"wallet_ref":{"type":"string"},"amount":{"description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`","type":"number"},"gateway_fee_percent":{"description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100.","type":"number"}}},"BasketLinks":{"properties":{"payment":{"description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status.","type":"string"},"checkout":{"description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment","type":"string"}}}}}}
```

## Update package quantity

> Sets the quantity of the given item in the basket. The user must be logged in before the quantity can be changed.\
> \
> \- \`{packageId}\` accepts the package's \`ident\` or numeric ID. Using \`ident\` is recommended, since it works for every package type.\
> \- Numeric IDs still work for standard packages.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Endpoints requiring only a basket ident with no token","name":"Baskets"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/{basketIdent}/packages/{packageId}":{"put":{"description":"Sets the quantity of the given item in the basket. The user must be logged in before the quantity can be changed.\n\n- `{packageId}` accepts the package's `ident` or numeric ID. Using `ident` is recommended, since it works for every package type.\n- Numeric IDs still work for standard packages.","operationId":"updatePackageQuantity","parameters":[{"$ref":"#/components/parameters/basketIdent"},{"description":"The package's `ident` (recommended) or numeric ID.","explode":false,"in":"path","name":"packageId","required":true,"schema":{"type":"string"},"style":"simple"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updatePackageQuantity_request"}}}},"responses":{"200":{"description":"Successful response."},"422":{"description":"The provided request is invalid. The error response will include detail as to which parameter failed validation."}},"summary":"Update package quantity","tags":["Baskets"]}}},"components":{"parameters":{"basketIdent":{"description":"The basket identifier.","explode":false,"in":"path","name":"basketIdent","required":true,"schema":{"type":"string"},"style":"simple"}},"schemas":{"updatePackageQuantity_request":{"properties":{"quantity":{"type":"integer"}}}}}}
```

## Update user's tier to a new package

> Updates a tier to a new package. A recurring payment updated webhook is sent when an update is successful.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"security":[{"basicAuth":[]}],"components":{"securitySchemes":{"basicAuth":{"scheme":"basic","type":"http"}},"schemas":{"updateTier_request":{"properties":{"package_id":{"type":"integer"}}},"UpdateTierResponse":{"properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}},"paths":{"/tiers/{tierId}":{"patch":{"description":"Updates a tier to a new package. A recurring payment updated webhook is sent when an update is successful.","operationId":"updateTier","parameters":[{"description":"The tier identifier","explode":false,"in":"path","name":"tierId","required":true,"schema":{"type":"integer"},"style":"simple"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateTier_request"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTierResponse"}}},"description":"Successful response."}},"summary":"Update user's tier to a new package","tags":["Headless"]}}}}
```

## Retrieves the available sidebar modules.

> Retrieves the available sidebar modules configured for the store.

```json
{"openapi":"3.1.0","info":{"title":"Tebex Headless API","version":"2.1.0"},"tags":[{"description":"Main API scoped to public token","name":"Headless"}],"servers":[{"description":"Main API scoped to public token","url":"https://headless.tebex.io/api/accounts/{token}","variables":{"token":{"default":"YOUR_PUBLIC_TOKEN","description":"The store's public token"}}}],"paths":{"/sidebar":{"get":{"description":"Retrieves the available sidebar modules configured for the store.","operationId":"getSidebar","parameters":[{"description":"The webstore identifier.","explode":false,"in":"path","name":"token","required":true,"schema":{"type":"string"},"style":"simple"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModulesResponse"}}},"description":"Successful response."}},"summary":"Retrieves the available sidebar modules.","tags":["Headless"]}}},"components":{"schemas":{"ModulesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Module"},"type":"array"}},"required":["data"]},"Module":{"discriminator":{"mapping":{"top_customer":"#/components/schemas/TopCustomerModule","textbox":"#/components/schemas/TextboxModule","recent_payments":"#/components/schemas/RecentPaymentsModule","featured_package":"#/components/schemas/FeaturedPackageModule","giftcard_balance":"#/components/schemas/GiftcardBalanceModule","server_status":"#/components/schemas/ServerStatusModule","payment_goal":"#/components/schemas/PaymentGoalModule","community_goal":"#/components/schemas/CommunityGoalModule"},"propertyName":"type"},"oneOf":[{"$ref":"#/components/schemas/TopCustomerModule"},{"$ref":"#/components/schemas/TextboxModule"},{"$ref":"#/components/schemas/RecentPaymentsModule"},{"$ref":"#/components/schemas/FeaturedPackageModule"},{"$ref":"#/components/schemas/GiftcardBalanceModule"},{"$ref":"#/components/schemas/ServerStatusModule"},{"$ref":"#/components/schemas/PaymentGoalModule"},{"$ref":"#/components/schemas/CommunityGoalModule"}]},"TopCustomerModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/TopCustomerData"}},"required":["data"]}]},"ModuleBase":{"properties":{"id":{"format":"int64","type":"integer"},"type":{"description":"Discriminator for module kind.","type":"string"},"start_time":{"format":"date-time","type":"string"},"end_time":{"description":"Nullable; when null the module is ongoing.","format":"date-time","nullable":true,"type":"string"},"data":{"description":"Type-specific payload.","type":"object"}},"required":["data","id","start_time","type"]},"TopCustomerData":{"properties":{"header":{"type":"string"},"username":{"type":"string"},"username_id":{"description":"User identifier.","type":"string"},"total":{"description":"Optional, present depending on module configuration.","type":"number"}},"required":["header","username","username_id"]},"TextboxModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/TextboxData"}},"required":["data"]}]},"TextboxData":{"properties":{"header":{"type":"string"},"text":{"description":"HTML supported.","type":"string"}},"required":["header","text"]},"RecentPaymentsModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/RecentPaymentsData"}},"required":["data"]}]},"RecentPaymentsData":{"properties":{"header":{"type":"string"},"payments":{"items":{"$ref":"#/components/schemas/RecentPayment"},"type":"array"}},"required":["header","payments"]},"RecentPayment":{"properties":{"username":{"type":"string"},"username_id":{"type":"string"},"package":{"$ref":"#/components/schemas/RecentPayment_package"},"created_at":{"description":"Optional, present depending on module configuration.","format":"date-time","nullable":true,"type":"string"},"price":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"currency":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"string"}},"required":["package","username","username_id"]},"RecentPayment_package":{"properties":{"name":{"type":"string"}},"required":["name"]},"FeaturedPackageModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/FeaturedPackageData"}},"required":["data"]}]},"FeaturedPackageData":{"properties":{"header":{"type":"string"},"package":{"$ref":"#/components/schemas/Package"}},"required":["header","package"]},"Package":{"properties":{"id":{"description":"The package's numeric ID. For external packages this is synthetic; use `ident` instead.","type":"integer"},"name":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","nullable":true},"type":{"type":"string"},"category":{"$ref":"#/components/schemas/Package_category"},"base_price":{"format":"float","type":"number"},"sales_tax":{"format":"float","type":"number"},"total_price":{"format":"float","type":"number"},"currency":{"type":"string"},"prorate_price":{"description":"If this package is part of a tiered category, this is the difference on upgrade pricing from the current active tier.","format":"float","type":"number","nullable":true},"discount":{"format":"float","type":"number"},"disable_quantity":{"type":"boolean"},"disable_gifting":{"type":"boolean"},"expiration_date":{"format":"date-time","type":"string","nullable":true},"media":{"items":{"$ref":"#/components/schemas/PackageMedia"},"type":"array"},"order":{"type":"integer"},"slug":{"type":"string"},"user_limit":{"type":"integer"},"creator_meta_data":{"type":"object"},"options":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"variables":{"items":{"description":"TODO default missing array inner type to string","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"},"ident":{"description":"The package's string identifier, returned on every package (standard, dynamic and external). Treat it as an opaque string: store it and send it back as-is to `getPackage` and `addBasketPackage`; don't build or parse it.\n\nIt has the form `{prefix}_{categoryId}_{id}`, where `prefix` is `pkg` (standard), `dyn` (dynamic, numeric id) or `ext` (external, e.g. `ext_10_{asset-uuid}` for INTRACT, with the provider's identifier URL-encoded).","type":"string"},"vip_status":{"description":"The package's VIP status. Only `null` has been observed so far, so the non-null type is unconfirmed.","type":"string","nullable":true}}},"Package_category":{"properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"PackageMedia":{"properties":{"type":{"enum":["video","image"],"type":"string"},"name":{"description":"A file name for the media, if applicable.","type":"string","nullable":true},"url":{"description":"The URL of the package media.","type":"string"},"featured":{"description":"True if this media should be featured more prominently than others.","type":"boolean"},"primary":{"description":"True if this is the primary media for the package.","type":"boolean"}}},"GiftcardBalanceModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/GiftcardBalanceData"}},"required":["data"]}]},"GiftcardBalanceData":{"properties":{"header":{"type":"string"}},"required":["header"]},"ServerStatusModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/ServerStatusData"}},"required":["data"]}]},"ServerStatusData":{"properties":{"header":{"type":"string"},"hostname":{"type":"string"},"port":{"type":"integer"},"online":{"type":"boolean"},"players":{"$ref":"#/components/schemas/Players"}},"required":["header","hostname","online","players","port"]},"Players":{"properties":{"online":{"type":"integer"},"max":{"type":"integer"}},"required":["max","online"]},"PaymentGoalModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/PaymentGoalData"}},"required":["data"]}]},"PaymentGoalData":{"properties":{"header":{"type":"string"},"percentage":{"maximum":100,"minimum":0,"type":"number"},"bar_style":{"enum":["normal","striped"],"type":"string"},"bar_animated":{"type":"boolean"},"total":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"target":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"}},"required":["bar_animated","bar_style","header","percentage"]},"CommunityGoalModule":{"allOf":[{"$ref":"#/components/schemas/ModuleBase"},{"properties":{"type":{},"data":{"$ref":"#/components/schemas/CommunityGoalData"}},"required":["data"]}]},"CommunityGoalData":{"properties":{"header":{"type":"string"},"bar_style":{"enum":["normal","striped"],"type":"string"},"bar_animated":{"type":"boolean"},"percentage":{"maximum":100,"minimum":0,"type":"number"},"total_payments":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"target":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"number"},"times_achieved":{"description":"Optional, present depending on module configuration.","nullable":true,"type":"integer"}},"required":["bar_animated","bar_style","header","percentage"]}}}}
```


# Overview

Develop advanced custom checkout experiences.

The Checkout API is designed to allow creators to use Tebex's Merchant of Record platform without the need to use a Tebex-powered webstore.&#x20;

If you haven't already done so, we recommend having a read of our [quick start guide](/developers/getting-started) before beginning integration.

This means creators can create baskets with **custom products** (as opposed to **pre-created** products on our webstore platform), and send customers directly to the checkout flow to proceed with payment.

The Checkout API can be used with [Tebex.js](/developers/tebex.js/overview) for a fully embedded checkout experience without the user ever leaving your own website.&#x20;

**Using the Checkout API requires prior approval from our compliance teams. Please note that the Checkout API is not available to some UGC creators, such as those on FiveM or RedM.**

## Terminology

<table><thead><tr><th width="150">Term</th><th width="595.4285714285713">Description</th></tr></thead><tbody><tr><td>Basket</td><td>To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing</td></tr><tr><td>Ident</td><td>A string identifier representing the basket</td></tr></tbody></table>

## Checkout API Flow

Below is the expected flow your application should follow when implementing the Checkout API. This should be considered a general guideline. For a full list of endpoints available, see the [Endpoints](/developers/checkout-api/endpoints) page.

You have two options for implementing Checkout API. We include a **Checkout** request where all data about the customer and their desired packages can be provided in one request.

### Option 1. Using the Checkout Request

If your app has existing basket functionality, we recommend using a **Checkout** request. You can send the details of your customer, basket, and sale information all in one request:

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/checkout" method="post" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

### Option 2. Using the Tebex Basket

If you do not have existing basket functionality in your app, you can use the Checkout API to fully manage the customer's basket on Tebex:

1. Create a basket for the customer.
   * Your app should save the `ident` value for reference later, as this is the identifier for this customer's basket.

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/baskets" method="post" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

2. Add or remove packages from the customer's basket as desired.

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/baskets/{ident}/packages" method="post" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/baskets/{ident}/packages/{rows.id}" method="delete" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

3. Add any desired sales / discounts to the basket

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/baskets/{ident}/sales" method="post" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

4. Direct the user to the basket's `links.checkout` URL in order to complete payment.

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/baskets/{ident}" method="get" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

5. After payment is complete, you may verify payment if you wish by checking the `links.payment` URL associated with the customer's basket.

## Recurring Payments

Tebex Checkout supports recurring payments in addition to single, one-time payments. Below are the endpoints you can use for managing a customer's recurring payments.

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/recurring-payments/{reference}" method="get" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/recurring-payments/{reference}" method="put" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/recurring-payments/{reference}" method="delete" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/recurring-payments/{reference}/status" method="put" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

## OpenAPI Schema and SDKs

Tebex Checkout is documented with OpenAPI. To view the schema and available SDKs, see our [releases](https://github.com/tebexio/TebexCheckout-OpenAPI/releases) on GitHub.

## Postman Schema

An importable Postman collection can always be downloaded from [Tebex Checkout's repository](https://github.com/tebexio/TebexCheckout-OpenAPI/releases) on GitHub.

## Examples

The following websites are integrated using the Checkout API.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td><strong>Lunarclient</strong></td><td><a href="https://store.lunarclient.com/">https://store.lunarclient.com/</a><br></td><td><a href="https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2F5WJPcmGAmzkn4fW7lDiZ%2Flunar.png?alt=media&amp;token=ece671c8-0c8f-40a7-8bc5-728494d4524d">lunar.png</a></td><td><a href="https://store.lunarclient.com/">https://store.lunarclient.com/</a></td></tr><tr><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>


# Headers and Authentication

As a creator using Checkout API, you must authenticate directly with the API as opposed to individual customers authenticating.

## Authorization

We use HTTP BASIC for authorization, and all requests are made over HTTPS so that your credentials are protected.

| Username **(Project ID)**  | Your Project ID (you can get this from <https://creator.tebex.io/developers/api-keys>)  |
| -------------------------- | --------------------------------------------------------------------------------------- |
| Password **(Private Key)** | Your Private Key (you can get this from <https://creator.tebex.io/developers/api-keys>) |

{% hint style="warning" %}
Your store's Private Key should **never** be shared publicly. If your key is ever compromised, it can be reset in your Webstore panel.
{% endhint %}

## Content Type

All requests use `application/json` as the `Content-Type`. Ensure this is set with all requests to our Checkout API.

### Example

```javascript
const url = "https://checkout.tebex.io/api/checkout";

const headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa(username + ':' + password));
headers.append('Content-Type', 'application/json');

const options = {
        method: 'POST', // Use 'GET', 'POST', 'PUT', etc. as needed
        headers: headers
};

const response = await fetch(url, options);
// etc
```


# Start the Checkout Process

When you are ready to redirect the customer to checkout, there are two ways of beginning the checkout experience:

## 1. Embedded - via Tebex.js

If you'd like the customer to remain on your website to complete their purchase, you're able to integrate **Tebex.js**, which is our embeddable checkout experience.&#x20;

Head over to the [Tebex.js documentation](/developers/tebex.js/overview) to get started.

## 2. External - via Redirect

You may also redirect the customer to an external checkout window using the following URL:&#x20;

`https://pay.tebex.io/{ident}`&#x20;

This is the same as the `links.checkout` value in a Basket API response. Where `{ident}` is the ident value returned when creating the basket.

{% hint style="warning" %}
When a customer starts their payment (is redirected to PayPal, provides their card details etc), a copy of the basket at that point in time is converted to a pending payment.

Any changes made to the basket after this point **will not be reflected** unless the checkout process is re-started.
{% endhint %}


# Checkout Webhooks

Your server can receive Webhooks from Tebex after events occur on our platform (successful payment, refunds, etc.)

Please see our [Webhooks Overview](/developers/webhooks/overview) for a guide on working with Webhooks.

{% hint style="warning" %}
Any webhooks sent to the server will contain the details of the **actual** items purchased (the basket at the point of payment).&#x20;

If your app manages its own basket, it is important to verify that webhook contents always match the items and amount you are expecting.
{% endhint %}


# Endpoints

## Fetch a basket by its identifier

> Gets the basket associated with the provided identifier.

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Baskets","description":"To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"Basket":{"type":"object","properties":{"ident":{"type":"string"},"expire":{"type":"string"},"price":{"type":"number","format":"float"},"priceDetails":{"$ref":"#/components/schemas/PriceDetails"},"isPaymentMethodUpdate":{"type":"boolean"},"returnUrl":{"type":"string","nullable":true},"complete":{"type":"boolean"},"tax":{"type":"number","format":"int32"},"username":{"type":"string","nullable":true},"email_immutable":{"type":"boolean"},"discounts":{"type":"array","items":{"$ref":"#/components/schemas/Discount"}},"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"address":{"$ref":"#/components/schemas/Address"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BasketRow"}},"fingerprint":{"type":"string","description":"Browser fingerprint to identify the user","nullable":true},"creator_code":{"type":"string","description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes"},"roundup":{"type":"boolean","nullable":true},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"recurring_items":{"type":"array","items":{"type":"object"}},"payment":{"type":"object","$ref":"#/components/schemas/Payment"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"PriceDetails":{"type":"object","properties":{"fullPrice":{"type":"number","format":"float"},"subTotal":{"type":"number","format":"float"},"discounts":{"type":"array","items":{"type":"object"}},"total":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"balance":{"type":"number","format":"float"},"sales":{"type":"array","items":{"$ref":"#/components/schemas/Sale"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"recurring":{"type":"boolean","description":"Contains recurring amount. Limited to 1 subscription package in the basket at a time."},"username":{"type":"string"},"roundUp":{"type":"number","nullable":true}}},"Sale":{"type":"object","properties":{"name":{"type":"string","description":"The name of the sale (displayed to the customer)"},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"The type of discount, either `percentage` for deducting a percentage of each item, or `amount` to deduct a fixed amount from each item."},"amount":{"type":"number","description":"The amount or percentage to deduct"}}},"GiftCard":{"type":"object"},"Discount":{"type":"object"},"Coupon":{"type":"object"},"Address":{"type":"object","properties":{"name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"address":{"type":"string"},"email":{"type":"string"},"state_id":{"type":"string","nullable":true},"country":{"type":"string"},"postal_code":{"type":"string"}}},"BasketRow":{"type":"object","properties":{"id":{"type":"integer"},"basket":{"type":"integer","description":"Numeric basket ID"},"package":{"type":"integer","nullable":true,"description":"Package ID associated with this item"},"override":{"type":"integer","description":"Package ID associated with this item"},"quantity":{"type":"integer"},"server":{"type":"integer","nullable":true},"price":{"type":"number","format":"float"},"gift_username_id":{"type":"integer","nullable":true},"options":{"type":"object","nullable":true},"recurring":{"type":"boolean"},"recurring_period":{"type":"string","nullable":true},"recurring_next_payment_date":{"type":"string","format":"date-time","nullable":true},"meta":{"type":"object","properties":{"name":{"type":"string"},"rowprice":{"type":"number","format":"float"},"initialprice":{"type":"number","format":"float"},"isCumulative":{"type":"boolean"},"requiredPackages":{"type":"array","items":{"type":"integer"}},"requiresAny":{"type":"boolean"},"category":{"type":"boolean"},"producesGiftCard":{"type":"boolean"},"allowsGiftCards":{"type":"boolean"},"servers":{"type":"array","items":{"type":"integer"}},"limits":{"type":"object","properties":{"user":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"global":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"packageExpiryTime":{"type":"integer"}}},"hasDeliverables":{"type":"boolean"},"deliverableTypes":{"type":"array","items":{"type":"string"}},"downloadLink":{"type":"string"},"hasSellerProtection":{"type":"boolean"},"itemType":{"type":"string","nullable":true},"revenue_share":{"type":"array","items":{"type":"number","format":"float"}},"image":{"type":"string","nullable":true},"realprice":{"type":"number","format":"float"}}},"custom":{"type":"object","nullable":true},"image_url":{"type":"string","nullable":true},"recurring_price":{"type":"number","format":"float","nullable":true}}},"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}},"BasketLinks":{"type":"object","properties":{"payment":{"type":"string","description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status."},"checkout":{"type":"string","description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment"}}}}},"paths":{"/baskets/{ident}":{"get":{"tags":["Baskets"],"operationId":"getBasketById","summary":"Fetch a basket by its identifier","parameters":[{"in":"path","name":"ident","schema":{"type":"string"},"required":true,"description":"The basket identifier."}],"description":"Gets the basket associated with the provided identifier.","responses":{"200":{"description":"Successful response returns the basket.\n\nThe `links.payment` property is only returned if the basket has been paid for, and a payment exist with the **complete**/**refund**/**chargeback** status.\n\nThe `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to in order to complete payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Basket"}}}},"404":{"description":"Basket not found."}}}}}}
```

## Create a basket that can be used to pay for items

> This will create and return a \`Basket\` that can be paid for by redirecting the user to \`links.checkout\`

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Baskets","description":"To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"Basket":{"type":"object","properties":{"ident":{"type":"string"},"expire":{"type":"string"},"price":{"type":"number","format":"float"},"priceDetails":{"$ref":"#/components/schemas/PriceDetails"},"isPaymentMethodUpdate":{"type":"boolean"},"returnUrl":{"type":"string","nullable":true},"complete":{"type":"boolean"},"tax":{"type":"number","format":"int32"},"username":{"type":"string","nullable":true},"email_immutable":{"type":"boolean"},"discounts":{"type":"array","items":{"$ref":"#/components/schemas/Discount"}},"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"address":{"$ref":"#/components/schemas/Address"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BasketRow"}},"fingerprint":{"type":"string","description":"Browser fingerprint to identify the user","nullable":true},"creator_code":{"type":"string","description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes"},"roundup":{"type":"boolean","nullable":true},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"recurring_items":{"type":"array","items":{"type":"object"}},"payment":{"type":"object","$ref":"#/components/schemas/Payment"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"PriceDetails":{"type":"object","properties":{"fullPrice":{"type":"number","format":"float"},"subTotal":{"type":"number","format":"float"},"discounts":{"type":"array","items":{"type":"object"}},"total":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"balance":{"type":"number","format":"float"},"sales":{"type":"array","items":{"$ref":"#/components/schemas/Sale"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"recurring":{"type":"boolean","description":"Contains recurring amount. Limited to 1 subscription package in the basket at a time."},"username":{"type":"string"},"roundUp":{"type":"number","nullable":true}}},"Sale":{"type":"object","properties":{"name":{"type":"string","description":"The name of the sale (displayed to the customer)"},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"The type of discount, either `percentage` for deducting a percentage of each item, or `amount` to deduct a fixed amount from each item."},"amount":{"type":"number","description":"The amount or percentage to deduct"}}},"GiftCard":{"type":"object"},"Discount":{"type":"object"},"Coupon":{"type":"object"},"Address":{"type":"object","properties":{"name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"address":{"type":"string"},"email":{"type":"string"},"state_id":{"type":"string","nullable":true},"country":{"type":"string"},"postal_code":{"type":"string"}}},"BasketRow":{"type":"object","properties":{"id":{"type":"integer"},"basket":{"type":"integer","description":"Numeric basket ID"},"package":{"type":"integer","nullable":true,"description":"Package ID associated with this item"},"override":{"type":"integer","description":"Package ID associated with this item"},"quantity":{"type":"integer"},"server":{"type":"integer","nullable":true},"price":{"type":"number","format":"float"},"gift_username_id":{"type":"integer","nullable":true},"options":{"type":"object","nullable":true},"recurring":{"type":"boolean"},"recurring_period":{"type":"string","nullable":true},"recurring_next_payment_date":{"type":"string","format":"date-time","nullable":true},"meta":{"type":"object","properties":{"name":{"type":"string"},"rowprice":{"type":"number","format":"float"},"initialprice":{"type":"number","format":"float"},"isCumulative":{"type":"boolean"},"requiredPackages":{"type":"array","items":{"type":"integer"}},"requiresAny":{"type":"boolean"},"category":{"type":"boolean"},"producesGiftCard":{"type":"boolean"},"allowsGiftCards":{"type":"boolean"},"servers":{"type":"array","items":{"type":"integer"}},"limits":{"type":"object","properties":{"user":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"global":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"packageExpiryTime":{"type":"integer"}}},"hasDeliverables":{"type":"boolean"},"deliverableTypes":{"type":"array","items":{"type":"string"}},"downloadLink":{"type":"string"},"hasSellerProtection":{"type":"boolean"},"itemType":{"type":"string","nullable":true},"revenue_share":{"type":"array","items":{"type":"number","format":"float"}},"image":{"type":"string","nullable":true},"realprice":{"type":"number","format":"float"}}},"custom":{"type":"object","nullable":true},"image_url":{"type":"string","nullable":true},"recurring_price":{"type":"number","format":"float","nullable":true}}},"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}},"BasketLinks":{"type":"object","properties":{"payment":{"type":"string","description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status."},"checkout":{"type":"string","description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment"}}}}},"paths":{"/baskets":{"post":{"tags":["Baskets"],"summary":"Create a basket that can be used to pay for items","description":"This will create and return a `Basket` that can be paid for by redirecting the user to `links.checkout`","operationId":"createBasket","requestBody":{"description":"Create a basket, returning the full basket object and payment link.","content":{"application/json":{"schema":{"type":"object","properties":{"return_url":{"type":"string","description":"The URL a customer can return to without completing checkout"},"complete_url":{"type":"string","description":"URL the customer can return to after completing payment"},"custom":{"type":"object","description":"Any custom data to be passed through the request. This will be returned in a post-completion webhook."},"first_name":{"type":"string","description":"The first name of the customer"},"last_name":{"type":"string","description":"The last name of the customer"},"email":{"type":"string","description":"The email address of the customer"},"complete_auto_redirect":{"type":"boolean","description":"Automatically redirect to the complete_url provided"},"country":{"type":"string","description":"An ISO 3166-1 alpha-2 character code representing the customer's country."},"creator_code":{"type":"string","description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes"},"ip":{"type":"string","description":"The IP address of the customer using this basket. Provide the IP if creating a basket on your server backend."}}}}}},"responses":{"200":{"description":"Basket created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Basket"}}}}}}}}}
```

## Add a package to the basket

> This adds a package (an object describing the product) to the basket \`{ident}\`. For subscriptions, \*\*only one subscription item may be in a basket at a time\*\*, and it cannot be included with one-time payment items. \*\*This endpoint requires prior approval. Please contact your account manager.\*\*

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Baskets","description":"To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"Package":{"type":"object","properties":{"name":{"type":"string","description":"The name of the item being purchased. This should be user-friendly as it is shown to the customer on checkout and receipts."},"price":{"type":"number","format":"float","description":"A float (decimal describing the price of the package in your account currency)"},"type":{"type":"string","enum":["single","subscription"]},"expiry_period":{"type":"string","enum":["day","month","year"],"description":"The renewal period of this item"},"expiry_length":{"type":"integer","description":"An integer representing the number of `expiry_periods` that make up the renewal period."},"custom":{"type":"object","description":"A map of data that is passed back to you via the webhook (for example, a tracking ID)"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}},"Basket":{"type":"object","properties":{"ident":{"type":"string"},"expire":{"type":"string"},"price":{"type":"number","format":"float"},"priceDetails":{"$ref":"#/components/schemas/PriceDetails"},"isPaymentMethodUpdate":{"type":"boolean"},"returnUrl":{"type":"string","nullable":true},"complete":{"type":"boolean"},"tax":{"type":"number","format":"int32"},"username":{"type":"string","nullable":true},"email_immutable":{"type":"boolean"},"discounts":{"type":"array","items":{"$ref":"#/components/schemas/Discount"}},"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"address":{"$ref":"#/components/schemas/Address"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BasketRow"}},"fingerprint":{"type":"string","description":"Browser fingerprint to identify the user","nullable":true},"creator_code":{"type":"string","description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes"},"roundup":{"type":"boolean","nullable":true},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"recurring_items":{"type":"array","items":{"type":"object"}},"payment":{"type":"object","$ref":"#/components/schemas/Payment"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"PriceDetails":{"type":"object","properties":{"fullPrice":{"type":"number","format":"float"},"subTotal":{"type":"number","format":"float"},"discounts":{"type":"array","items":{"type":"object"}},"total":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"balance":{"type":"number","format":"float"},"sales":{"type":"array","items":{"$ref":"#/components/schemas/Sale"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"recurring":{"type":"boolean","description":"Contains recurring amount. Limited to 1 subscription package in the basket at a time."},"username":{"type":"string"},"roundUp":{"type":"number","nullable":true}}},"Sale":{"type":"object","properties":{"name":{"type":"string","description":"The name of the sale (displayed to the customer)"},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"The type of discount, either `percentage` for deducting a percentage of each item, or `amount` to deduct a fixed amount from each item."},"amount":{"type":"number","description":"The amount or percentage to deduct"}}},"GiftCard":{"type":"object"},"Discount":{"type":"object"},"Coupon":{"type":"object"},"Address":{"type":"object","properties":{"name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"address":{"type":"string"},"email":{"type":"string"},"state_id":{"type":"string","nullable":true},"country":{"type":"string"},"postal_code":{"type":"string"}}},"BasketRow":{"type":"object","properties":{"id":{"type":"integer"},"basket":{"type":"integer","description":"Numeric basket ID"},"package":{"type":"integer","nullable":true,"description":"Package ID associated with this item"},"override":{"type":"integer","description":"Package ID associated with this item"},"quantity":{"type":"integer"},"server":{"type":"integer","nullable":true},"price":{"type":"number","format":"float"},"gift_username_id":{"type":"integer","nullable":true},"options":{"type":"object","nullable":true},"recurring":{"type":"boolean"},"recurring_period":{"type":"string","nullable":true},"recurring_next_payment_date":{"type":"string","format":"date-time","nullable":true},"meta":{"type":"object","properties":{"name":{"type":"string"},"rowprice":{"type":"number","format":"float"},"initialprice":{"type":"number","format":"float"},"isCumulative":{"type":"boolean"},"requiredPackages":{"type":"array","items":{"type":"integer"}},"requiresAny":{"type":"boolean"},"category":{"type":"boolean"},"producesGiftCard":{"type":"boolean"},"allowsGiftCards":{"type":"boolean"},"servers":{"type":"array","items":{"type":"integer"}},"limits":{"type":"object","properties":{"user":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"global":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"packageExpiryTime":{"type":"integer"}}},"hasDeliverables":{"type":"boolean"},"deliverableTypes":{"type":"array","items":{"type":"string"}},"downloadLink":{"type":"string"},"hasSellerProtection":{"type":"boolean"},"itemType":{"type":"string","nullable":true},"revenue_share":{"type":"array","items":{"type":"number","format":"float"}},"image":{"type":"string","nullable":true},"realprice":{"type":"number","format":"float"}}},"custom":{"type":"object","nullable":true},"image_url":{"type":"string","nullable":true},"recurring_price":{"type":"number","format":"float","nullable":true}}},"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"BasketLinks":{"type":"object","properties":{"payment":{"type":"string","description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status."},"checkout":{"type":"string","description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment"}}}}},"paths":{"/baskets/{ident}/packages":{"post":{"parameters":[{"in":"path","name":"ident","schema":{"type":"string"},"required":true,"description":"The basket identifier."}],"tags":["Baskets"],"operationId":"addPackage","summary":"Add a package to the basket","description":"This adds a package (an object describing the product) to the basket `{ident}`. For subscriptions, **only one subscription item may be in a basket at a time**, and it cannot be included with one-time payment items. **This endpoint requires prior approval. Please contact your account manager.**","requestBody":{"content":{"application/json":{"schema":{"properties":{"package":{"$ref":"#/components/schemas/Package"},"qty":{"type":"integer","description":"The quantity of `package` in this basket. This is not the total quantity of overall items in the basket."},"type":{"type":"string","enum":["single","subscription"],"description":"The type of payment, either `single` for one-time payments or `subscription`.","required":["single"]},"revenue_share":{"type":"array","description":"An array of payment destination objects describing how the purchase should be split between multiple wallets. **Only available with pre-agreement from Tebex.**","items":{"$ref":"#/components/schemas/RevenueShare"}}}}}}},"responses":{"200":{"description":"Package is successfully added to the basket, and basket is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Basket"}}}},"400":{"description":"Improperly formatted package. See ErrorResponse."},"404":{"description":"Basket not found."}}}}}}
```

## Remove a row from the basket

> This will remove the given \`{rows.id}\` from the basket \`{ident}\`. The basket must be re-fetched after running to receive updated totals.

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Baskets","description":"To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}}},"paths":{"/baskets/{ident}/packages/{rows.id}":{"delete":{"parameters":[{"in":"path","name":"ident","schema":{"type":"string"},"required":true,"description":"The basket identifier."},{"in":"path","name":"rows.id","schema":{"type":"integer"},"required":true,"description":"The `id` of the `basket.rows` row to remove."}],"tags":["Baskets"],"operationId":"removeRowFromBasket","summary":"Remove a row from the basket","description":"This will remove the given `{rows.id}` from the basket `{ident}`. The basket must be re-fetched after running to receive updated totals.","responses":{"204":{"description":"Successfully deleted a row from the basket."},"404":{"description":"Row or basket not found."}}}}}}
```

## Add a sale to the basket

> Adds a \`Sale\` to the basket with \`{ident}\`. \*\*Sales cannot be applied to baskets with \`revenue\_share\` set.\*\*

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Baskets","description":"To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"Sale":{"type":"object","properties":{"name":{"type":"string","description":"The name of the sale (displayed to the customer)"},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"The type of discount, either `percentage` for deducting a percentage of each item, or `amount` to deduct a fixed amount from each item."},"amount":{"type":"number","description":"The amount or percentage to deduct"}}},"Basket":{"type":"object","properties":{"ident":{"type":"string"},"expire":{"type":"string"},"price":{"type":"number","format":"float"},"priceDetails":{"$ref":"#/components/schemas/PriceDetails"},"isPaymentMethodUpdate":{"type":"boolean"},"returnUrl":{"type":"string","nullable":true},"complete":{"type":"boolean"},"tax":{"type":"number","format":"int32"},"username":{"type":"string","nullable":true},"email_immutable":{"type":"boolean"},"discounts":{"type":"array","items":{"$ref":"#/components/schemas/Discount"}},"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"address":{"$ref":"#/components/schemas/Address"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BasketRow"}},"fingerprint":{"type":"string","description":"Browser fingerprint to identify the user","nullable":true},"creator_code":{"type":"string","description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes"},"roundup":{"type":"boolean","nullable":true},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"recurring_items":{"type":"array","items":{"type":"object"}},"payment":{"type":"object","$ref":"#/components/schemas/Payment"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"PriceDetails":{"type":"object","properties":{"fullPrice":{"type":"number","format":"float"},"subTotal":{"type":"number","format":"float"},"discounts":{"type":"array","items":{"type":"object"}},"total":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"balance":{"type":"number","format":"float"},"sales":{"type":"array","items":{"$ref":"#/components/schemas/Sale"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"recurring":{"type":"boolean","description":"Contains recurring amount. Limited to 1 subscription package in the basket at a time."},"username":{"type":"string"},"roundUp":{"type":"number","nullable":true}}},"GiftCard":{"type":"object"},"Discount":{"type":"object"},"Coupon":{"type":"object"},"Address":{"type":"object","properties":{"name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"address":{"type":"string"},"email":{"type":"string"},"state_id":{"type":"string","nullable":true},"country":{"type":"string"},"postal_code":{"type":"string"}}},"BasketRow":{"type":"object","properties":{"id":{"type":"integer"},"basket":{"type":"integer","description":"Numeric basket ID"},"package":{"type":"integer","nullable":true,"description":"Package ID associated with this item"},"override":{"type":"integer","description":"Package ID associated with this item"},"quantity":{"type":"integer"},"server":{"type":"integer","nullable":true},"price":{"type":"number","format":"float"},"gift_username_id":{"type":"integer","nullable":true},"options":{"type":"object","nullable":true},"recurring":{"type":"boolean"},"recurring_period":{"type":"string","nullable":true},"recurring_next_payment_date":{"type":"string","format":"date-time","nullable":true},"meta":{"type":"object","properties":{"name":{"type":"string"},"rowprice":{"type":"number","format":"float"},"initialprice":{"type":"number","format":"float"},"isCumulative":{"type":"boolean"},"requiredPackages":{"type":"array","items":{"type":"integer"}},"requiresAny":{"type":"boolean"},"category":{"type":"boolean"},"producesGiftCard":{"type":"boolean"},"allowsGiftCards":{"type":"boolean"},"servers":{"type":"array","items":{"type":"integer"}},"limits":{"type":"object","properties":{"user":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"global":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"packageExpiryTime":{"type":"integer"}}},"hasDeliverables":{"type":"boolean"},"deliverableTypes":{"type":"array","items":{"type":"string"}},"downloadLink":{"type":"string"},"hasSellerProtection":{"type":"boolean"},"itemType":{"type":"string","nullable":true},"revenue_share":{"type":"array","items":{"type":"number","format":"float"}},"image":{"type":"string","nullable":true},"realprice":{"type":"number","format":"float"}}},"custom":{"type":"object","nullable":true},"image_url":{"type":"string","nullable":true},"recurring_price":{"type":"number","format":"float","nullable":true}}},"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}},"BasketLinks":{"type":"object","properties":{"payment":{"type":"string","description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status."},"checkout":{"type":"string","description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment"}}}}},"paths":{"/baskets/{ident}/sales":{"post":{"parameters":[{"in":"path","name":"ident","schema":{"type":"string"},"required":true,"description":"The basket identifier."}],"tags":["Baskets"],"operationId":"addSaleToBasket","summary":"Add a sale to the basket","description":"Adds a `Sale` to the basket with `{ident}`. **Sales cannot be applied to baskets with `revenue_share` set.**","requestBody":{"description":"Provide a `Sale` as an object to apply it to the basket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sale"}}}},"responses":{"200":{"description":"Successfully adds sale to basket.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Basket"}}}},"400":{"description":"Bad request. Improperly formatted Sale or this basket cannot accept sales. See ErrorResponse."},"404":{"description":"Basket not found."}}}}}}
```

## Create a checkout request

> This API call allows the complete checkout flow (create basket, add items, add sale) to be made in a single API call, for when the Seller is managing the basket locally. \*\*This endpoint requires prior approval - please contact your account manager.\*\*

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"CheckoutItem":{"type":"object","description":"An item added to a basket as part of the `/checkout` request.","properties":{"package":{"$ref":"#/components/schemas/Package"},"qty":{"type":"integer","description":"The quantity of `package` to add to the basket. This must be provided alongside `package`, not inside it - a `qty` nested within the package object is silently ignored and the item is added with a quantity of 1."}}},"Package":{"type":"object","properties":{"name":{"type":"string","description":"The name of the item being purchased. This should be user-friendly as it is shown to the customer on checkout and receipts."},"price":{"type":"number","format":"float","description":"A float (decimal describing the price of the package in your account currency)"},"type":{"type":"string","enum":["single","subscription"]},"expiry_period":{"type":"string","enum":["day","month","year"],"description":"The renewal period of this item"},"expiry_length":{"type":"integer","description":"An integer representing the number of `expiry_periods` that make up the renewal period."},"custom":{"type":"object","description":"A map of data that is passed back to you via the webhook (for example, a tracking ID)"}}},"Sale":{"type":"object","properties":{"name":{"type":"string","description":"The name of the sale (displayed to the customer)"},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"The type of discount, either `percentage` for deducting a percentage of each item, or `amount` to deduct a fixed amount from each item."},"amount":{"type":"number","description":"The amount or percentage to deduct"}}},"Basket":{"type":"object","properties":{"ident":{"type":"string"},"expire":{"type":"string"},"price":{"type":"number","format":"float"},"priceDetails":{"$ref":"#/components/schemas/PriceDetails"},"isPaymentMethodUpdate":{"type":"boolean"},"returnUrl":{"type":"string","nullable":true},"complete":{"type":"boolean"},"tax":{"type":"number","format":"int32"},"username":{"type":"string","nullable":true},"email_immutable":{"type":"boolean"},"discounts":{"type":"array","items":{"$ref":"#/components/schemas/Discount"}},"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"address":{"$ref":"#/components/schemas/Address"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BasketRow"}},"fingerprint":{"type":"string","description":"Browser fingerprint to identify the user","nullable":true},"creator_code":{"type":"string","description":"The creator code is used to share a percentage of the payment with another party. See more about creator codes at https://docs.tebex.io/creators/tebex-control-panel/engagement/creator-codes"},"roundup":{"type":"boolean","nullable":true},"cancel_url":{"type":"string"},"complete_url":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean"},"recurring_items":{"type":"array","items":{"type":"object"}},"payment":{"type":"object","$ref":"#/components/schemas/Payment"},"custom":{"type":"object","nullable":true},"links":{"$ref":"#/components/schemas/BasketLinks"}}},"PriceDetails":{"type":"object","properties":{"fullPrice":{"type":"number","format":"float"},"subTotal":{"type":"number","format":"float"},"discounts":{"type":"array","items":{"type":"object"}},"total":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"balance":{"type":"number","format":"float"},"sales":{"type":"array","items":{"$ref":"#/components/schemas/Sale"}},"giftcards":{"type":"array","items":{"$ref":"#/components/schemas/GiftCard"}},"recurring":{"type":"boolean","description":"Contains recurring amount. Limited to 1 subscription package in the basket at a time."},"username":{"type":"string"},"roundUp":{"type":"number","nullable":true}}},"GiftCard":{"type":"object"},"Discount":{"type":"object"},"Coupon":{"type":"object"},"Address":{"type":"object","properties":{"name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"address":{"type":"string"},"email":{"type":"string"},"state_id":{"type":"string","nullable":true},"country":{"type":"string"},"postal_code":{"type":"string"}}},"BasketRow":{"type":"object","properties":{"id":{"type":"integer"},"basket":{"type":"integer","description":"Numeric basket ID"},"package":{"type":"integer","nullable":true,"description":"Package ID associated with this item"},"override":{"type":"integer","description":"Package ID associated with this item"},"quantity":{"type":"integer"},"server":{"type":"integer","nullable":true},"price":{"type":"number","format":"float"},"gift_username_id":{"type":"integer","nullable":true},"options":{"type":"object","nullable":true},"recurring":{"type":"boolean"},"recurring_period":{"type":"string","nullable":true},"recurring_next_payment_date":{"type":"string","format":"date-time","nullable":true},"meta":{"type":"object","properties":{"name":{"type":"string"},"rowprice":{"type":"number","format":"float"},"initialprice":{"type":"number","format":"float"},"isCumulative":{"type":"boolean"},"requiredPackages":{"type":"array","items":{"type":"integer"}},"requiresAny":{"type":"boolean"},"category":{"type":"boolean"},"producesGiftCard":{"type":"boolean"},"allowsGiftCards":{"type":"boolean"},"servers":{"type":"array","items":{"type":"integer"}},"limits":{"type":"object","properties":{"user":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"global":{"type":"object","properties":{"enabled":{"type":"boolean"},"timestamp":{"type":"integer"},"limit":{"type":"boolean"}}},"packageExpiryTime":{"type":"integer"}}},"hasDeliverables":{"type":"boolean"},"deliverableTypes":{"type":"array","items":{"type":"string"}},"downloadLink":{"type":"string"},"hasSellerProtection":{"type":"boolean"},"itemType":{"type":"string","nullable":true},"revenue_share":{"type":"array","items":{"type":"number","format":"float"}},"image":{"type":"string","nullable":true},"realprice":{"type":"number","format":"float"}}},"custom":{"type":"object","nullable":true},"image_url":{"type":"string","nullable":true},"recurring_price":{"type":"number","format":"float","nullable":true}}},"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}},"BasketLinks":{"type":"object","properties":{"payment":{"type":"string","description":"The `links.payment` property is only returned if the basket has been paid for and a payment exists with the `complete`,`refund`, or `chargeback` status."},"checkout":{"type":"string","description":"The `links.checkout` property is only returned if the basket has not been paid, and is the URL to send the customer to make payment"}}}}},"paths":{"/checkout":{"post":{"tags":["Checkout"],"operationId":"checkout","summary":"Create a checkout request","description":"This API call allows the complete checkout flow (create basket, add items, add sale) to be made in a single API call, for when the Seller is managing the basket locally. **This endpoint requires prior approval - please contact your account manager.**","requestBody":{"description":"Provide a `Basket`, an array of `Packages` to be added to the basket, and an optional `Sale` to complete the full checkout flow in one call. **Only one subscription item may be in the basket at a time.**","content":{"application/json":{"schema":{"required":["basket","items"],"properties":{"basket":{"description":"An object containing the customer's information, relevant links, and any custom tracking data.","type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"return_url":{"type":"string"},"complete_url":{"type":"string"},"custom":{"type":"object"}}},"items":{"type":"array","description":"An array of `Packages` in the basket.","items":{"$ref":"#/components/schemas/CheckoutItem"}},"sale":{"$ref":"#/components/schemas/Sale"}}}}}},"responses":{"200":{"description":"Successfully created basket. The basket will be returned with `links` containing the URLs you should direct the customer to in order to complete payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Basket"}}}},"400":{"description":"Bad Request. See ErrorResponse."}}}}}}
```

## Fetch a payment by its transaction ID

> This will fetch the given payment associated with this transaction id. Single payment transaction IDs begin with \`tbx-\`

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Payments","description":"Single payments (`tbx-`) can be fetched and refunded with a valid reference id."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}}}},"paths":{"/payments/{txnId}?type=txn_id":{"get":{"tags":["Payments"],"operationId":"getPaymentById","summary":"Fetch a payment by its transaction ID","description":"This will fetch the given payment associated with this transaction id. Single payment transaction IDs begin with `tbx-`","parameters":[{"in":"path","name":"txnId","schema":{"type":"string"},"required":true,"description":"The payment reference to fetch."}],"responses":{"200":{"description":"Payment fetched successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"404":{"description":"Transaction not found."}}}}}}
```

## Refund a payment by its transaction ID

> This will refund the given payment associated with this transaction id.

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Payments","description":"Single payments (`tbx-`) can be fetched and refunded with a valid reference id."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"Payment":{"type":"object","nullable":true,"properties":{"transaction_id":{"type":"string"},"status":{"type":"object","properties":{"id":{"type":"integer"},"description":{"type":"string"}}},"payment_sequence":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"price_paid":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"payment_method":{"type":"object","properties":{"name":{},"refundable":{"type":"boolean"}}},"revenue_share":{"type":"array","items":{"$ref":"#/components/schemas/RevenueShare"}},"decline_reason":{"type":"string"},"fees":{"type":"object","properties":{"tax":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"gateway":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}}}},"customer":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"ip":{"type":"string"},"username":{"type":"string","nullable":true},"marketing_consent":{"type":"boolean"},"country":{"type":"string"},"postal_code":{"type":"string","nullable":true}}},"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","nullable":true},"name":{"type":"string"},"quantity":{"type":"integer"},"base_price":{"properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"paid_price":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"currency":{"type":"string"}}},"variables":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","format":"date-time","nullable":true},"custom":{"type":"object","description":"Any custom data associated with the payment"},"username":{"type":"string","nullable":true}}}},"coupons":{"type":"array","items":{"type":"object"}},"gift_cards":{"type":"array","items":{"type":"object"}},"recurring_payment_reference":{"type":"string","nullable":true},"custom":{"type":"object"}}},"RevenueShare":{"type":"object","nullable":true,"properties":{"wallet_ref":{"type":"string"},"amount":{"type":"number","format":"float","description":"A float (decimal) value representing the amount of this payment in your account currency that is credited to the `wallet_ref`"},"gateway_fee_percent":{"type":"number","format":"float","description":"A float (decimal) value representing the percentage of the gateway fee that should be dedicated from this wallet’s revenue share. This optional value can be anywhere between 0 - 100."}}}}},"paths":{"/payments/{txnId}/refund?type=txn_id":{"post":{"tags":["Payments"],"operationId":"refundPaymentById","summary":"Refund a payment by its transaction ID","description":"This will refund the given payment associated with this transaction id.","parameters":[{"in":"path","name":"txnId","schema":{"type":"string"},"required":true,"description":"The payment reference to refund."}],"responses":{"200":{"description":"Payment refunded successfully. The payment details are returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"404":{"description":"Payment not found."},"422":{"description":"The payment cannot be refunded. Payments can only be refunded when a payment's `status` is Completed."}}}}}}
```

## GET /recurring-payments/{reference}

> Fetch a recurring payment (subscription) by its reference

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Recurring Payments","description":"Payments with reference IDs like `tbx-r-`. Can be paused, reeactivated, and cancelled provided a valid reference id."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"RecurringPayment":{"type":"object","properties":{"id":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"paused_at":{"type":"string","format":"date-time","nullable":true},"paused_until":{"type":"string","format":"date-time","nullable":true},"next_payment_date":{"type":"string"},"reference":{"type":"string"},"account_id":{"type":"integer"},"interval":{"type":"string"},"cancelled_at":{"type":"string","format":"date-time","nullable":true},"cancellation_requested_at":{"type":"string","format":"date-time","nullable":true},"status":{"type":"object","properties":{"id":{"type":"integer"},"class":{"type":"string"},"description":{"type":"string"},"active":{"type":"integer"}}},"amount":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"period":{"type":"string"}}},"cancel_reason":{"type":"string","nullable":true},"links":{"type":"object","properties":{"initial_payment":{"type":"string"},"payment_history":{"type":"array","items":{"type":"string"}}}}}}}},"paths":{"/recurring-payments/{reference}":{"get":{"tags":["Recurring Payments"],"operationId":"getRecurringPayment","summary":"Fetch a recurring payment (subscription) by its reference","parameters":[{"in":"path","name":"reference","schema":{"type":"string"},"required":true,"description":"The recurring payment reference to fetch."}],"responses":{"200":{"description":"Successfully fetched recurring payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringPayment"}}}},"404":{"description":"Recurring payment not found."}}}}}}
```

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/recurring-payments/{reference}" method="put" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

{% openapi src="/files/9GpXba7VxXu1zKOFJQ2I" path="/recurring-payments/{reference}" method="delete" %}
[checkout-api.yaml](https://924803319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaRz9HUAxrYuZsSDWhYnu%2Fuploads%2FxlNyfP91gTDjFnH9lvfH%2Fcheckout-api.yaml?alt=media\&token=b7e53337-137e-47cd-885f-bbea7aa22554)
{% endopenapi %}

## PUT /recurring-payments/{reference}/status

> Pause or reactivate a recurring payment

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Recurring Payments","description":"Payments with reference IDs like `tbx-r-`. Can be paused, reeactivated, and cancelled provided a valid reference id."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}},"schemas":{"RecurringPayment":{"type":"object","properties":{"id":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"paused_at":{"type":"string","format":"date-time","nullable":true},"paused_until":{"type":"string","format":"date-time","nullable":true},"next_payment_date":{"type":"string"},"reference":{"type":"string"},"account_id":{"type":"integer"},"interval":{"type":"string"},"cancelled_at":{"type":"string","format":"date-time","nullable":true},"cancellation_requested_at":{"type":"string","format":"date-time","nullable":true},"status":{"type":"object","properties":{"id":{"type":"integer"},"class":{"type":"string"},"description":{"type":"string"},"active":{"type":"integer"}}},"amount":{"type":"object","properties":{"amount":{"type":"number","format":"float"},"tax":{"type":"number","format":"float"},"period":{"type":"string"}}},"cancel_reason":{"type":"string","nullable":true},"links":{"type":"object","properties":{"initial_payment":{"type":"string"},"payment_history":{"type":"array","items":{"type":"string"}}}}}}}},"paths":{"/recurring-payments/{reference}/status":{"put":{"tags":["Recurring Payments"],"operationId":"updateRecurringPayment","summary":"Pause or reactivate a recurring payment","parameters":[{"in":"path","name":"reference","schema":{"type":"string"},"required":true,"description":"The recurring payment reference to update."}],"requestBody":{"content":{"application/json":{"schema":{"required":["status"],"properties":{"status":{"type":"string","enum":["Paused","Active"],"description":"Your desired state of the recurring payment. Provide `Paused` with `paused_until` to pause a recurring payment. Otherwise, provide `Active` to resume a recurring payment."},"paused_until":{"type":"string","description":"To pause a payment, provide a ISO8601 formatted date on which the payment should be reactivated."}}}}}},"responses":{"200":{"description":"Successfully paused or reactivated a payment. The `RecurringPayment` is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringPayment"}}}},"404":{"description":"Recurring payment not found."},"422":{"description":"Unprocessible Entity. An invalid status was provided or the recurring payment cannot be processed. See ErrorResponse."}}}}}}
```

## Update a basket's details, including expiry date.

> This will update the customer's details on the basket. If the customer is already logged in and a new email is provided, they will be logged out.

```json
{"openapi":"3.0.3","info":{"title":"Tebex Checkout API","version":"1.1.5"},"tags":[{"name":"Baskets","description":"To start a transaction, a basket must be created. The basket, similar to a standard eCommerce basket will contain the items that the customer is purchasing."}],"servers":[{"url":"https://checkout.tebex.io/api"}],"security":[{"tebex_checkout_auth_basic":[]}],"components":{"securitySchemes":{"tebex_checkout_auth_basic":{"type":"http","scheme":"basic"}}},"paths":{"/baskets/{ident}":{"put":{"tags":["Baskets"],"summary":"Update a basket's details, including expiry date.","parameters":[{"in":"path","name":"ident","schema":{"type":"string"},"required":true,"description":"The basket identifier."}],"description":"This will update the customer's details on the basket. If the customer is already logged in and a new email is provided, they will be logged out.","operationId":"updateBasket","requestBody":{"description":"The parameters of the basket you wish to update.","content":{"application/json":{"schema":{"type":"object","properties":{"country":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"state_id":{"type":"string","nullable":true},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"postal_code":{"type":"string","nullable":true},"creator_code":{"type":"string","nullable":true},"complete_auto_redirect":{"type":"boolean","nullable":true},"expires_at":{"type":"string","format":"date-time","description":"An ISO8601 formatted date. After this date the basket cannot be used to checkout.","nullable":true}}}}}},"responses":{"200":{"description":"Basket updated successfully"},"404":{"description":"Basket not found."}}}}}}
```


# Errors

All errors returned by the Tebex Checkout APIs follow the RFC 7807 standard (<https://datatracker.ietf.org/doc/html/rfc7807#section-3.1>).

We also use standardised HTTP response codes to describe each error:

1. **400 Bad Request** - User data validation error
2. **401 / 403 - Authentication / Authorization** (depending on if it's pre- or post- authentication
3. **404** - Requested resource doesn't exist
4. **5xx** - Server side transitory errors.

```javascript
{
  "type": "Not Found",
  "title": "Resource not found",
  "status": 404,
  "detail": "The requested resource does not exist.",
  "instance": "/account/12345"
}
```




---

[Next Page](https://docs.tebex.io/developers/llms-full.txt/1)

