> For the complete documentation index, see [llms.txt](https://docs.drakodevelopment.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.drakodevelopment.net/addon-system/api-integration/store-api.md).

# Store API

## ✨ Features

* **Per-server stores** — Each guild has its own store
* **Multiple categories** — Pets, roles, boosters, titles, items, special
* **Reward types** — Pets, roles, boosters, titles, items, custom
* **Requirements** — Level and prestige requirements
* **Stock management** — Limited or unlimited stock
* **Purchase limits** — Max purchases per user
* **Transaction logging** — Full purchase history

## 🚀 Quick Start

The Store API is available globally as `global.storeAPI` — no require needed.

{% code title="quick-start.js" expandable="true" %}

```javascript
// Add a custom item
await global.storeAPI.addItem(guildId, {
    name: 'VIP Role',
    category: 'roles',
    price: 50000,
    rewardType: 'role',
    rewardData: { roleId: '123456789', roleDuration: null },
    emoji: '👑'
});

// Get all items in a category
const pets = await global.storeAPI.getItems(guildId, 'pets');

// Purchase an item for a user
const result = await global.storeAPI.purchaseItem(guildId, userId, itemId);
if (result.success) {
    console.log(`Purchased: ${result.item.name}`);
}
```

{% endcode %}

## 📦 Methods Reference

### addItem(guildId, itemData)

Add a new item to the store.

{% code title="addItem example" expandable="true" %}

```javascript
await global.storeAPI.addItem(guildId, {
    name: 'Dragon Pet',
    description: 'A legendary beast',
    category: 'pets',           // pets, roles, boosters, titles, items, special
    price: 50000,
    stock: -1,                  // -1 = unlimited
    maxPerUser: 1,              // -1 = unlimited
    enabled: true,
    rewardType: 'pet',
    rewardData: {
        petType: 'Dragon',
        petMultiplier: 1.15,
        petPassiveIncome: 100
    },
    requirements: {
        level: 10,
        prestige: 0
    },
    emoji: '🐉',
    color: '#FF4500',
    featured: true,
    sortOrder: 1
});
```

{% endcode %}

### removeItem(guildId, itemId)

Remove an item from the store.

{% code title="removeItem example" %}

```javascript
const removed = await global.storeAPI.removeItem(guildId, 'item-uuid');
// Returns: true if deleted, false if not found
```

{% endcode %}

### updateItem(guildId, itemId, updates)

Update an existing item.

{% code title="updateItem example" %}

```javascript
await global.storeAPI.updateItem(guildId, 'item-uuid', {
    price: 75000,
    'metadata.featured': true,
    enabled: false
});
```

{% endcode %}

### getItem(guildId, itemId)

Get a single item by ID.

{% code title="getItem example" %}

```javascript
const item = await global.storeAPI.getItem(guildId, 'item-uuid');
```

{% endcode %}

### getItems(guildId, category?)

Get all items, optionally filtered by category.

{% code title="getItems examples" %}

```javascript
// All items
const allItems = await global.storeAPI.getItems(guildId);

// Only pets
const pets = await global.storeAPI.getItems(guildId, 'pets');

// Only boosters
const boosters = await global.storeAPI.getItems(guildId, 'boosters');
```

{% endcode %}

### getCategories(guildId)

Get all categories that have items.

{% code title="getCategories example" %}

```javascript
const categories = await global.storeAPI.getCategories(guildId);
// Returns: ['pets', 'boosters', 'titles']
```

{% endcode %}

### getFeaturedItems(guildId)

Get all featured items.

{% code title="getFeaturedItems example" %}

```javascript
const featured = await global.storeAPI.getFeaturedItems(guildId);
```

{% endcode %}

### purchaseItem(guildId, userId, itemId, client?)

Process a purchase. Handles balance deduction, requirements validation, stock management, and reward application.

The `client` parameter is optional — if not provided, the API uses the client from its context.

{% code title="purchaseItem example" %}

```javascript
const result = await global.storeAPI.purchaseItem(guildId, userId, itemId);

if (result.success) {
    console.log(result.item);     // The purchased item
    console.log(result.purchase); // Purchase record
    console.log(result.reward);   // Reward message string
} else {
    console.log(result.error);    // Error message
}
```

{% endcode %}

Possible errors:

* Item not found
* Item out of stock
* User not found
* Insufficient funds
* Requires level X
* Requires prestige X
* Purchase limit reached
* You already own this pet!

### getUserPurchases(guildId, userId)

Get a user's purchase history.

{% code title="getUserPurchases example" %}

```javascript
const purchases = await global.storeAPI.getUserPurchases(guildId, userId);
// Returns array of purchase records sorted by date (newest first)
```

{% endcode %}

## 🎁 Reward Types

### pet

Adds a pet to the user's collection.

{% code title="pet reward example" %}

```javascript
rewardType: 'pet',
rewardData: {
    petType: 'Dragon',        // Pet type name
    petMultiplier: 1.15,      // Earnings multiplier (1.15 = +15%)
    petPassiveIncome: 100     // Coins per hour passive income
}
```

{% endcode %}

### role

Grants a Discord role to the user.

{% code title="role reward example" %}

```javascript
rewardType: 'role',
rewardData: {
    roleId: '123456789012345678',  // Discord role ID
    roleDuration: 2592000000       // Duration in ms (null = permanent)
}
```

{% endcode %}

### booster

Activates a temporary multiplier booster.

{% code title="booster reward example" %}

```javascript
rewardType: 'booster',
rewardData: {
    boosterType: 'Money',       // 'Money' or 'XP'
    boosterMultiplier: 1.5,     // 1.5 = +50% bonus
    boosterDuration: 86400000   // Duration in ms (24 hours)
}
```

{% endcode %}

### title

Unlocks a display title for the user.

{% code title="title reward example" %}

```javascript
rewardType: 'title',
rewardData: {
    title: '💰 Rich'   // The title string
}
```

{% endcode %}

### item

Adds a generic item to user's inventory.

{% code title="item reward example" %}

```javascript
rewardType: 'item',
rewardData: {
    itemType: 'charm',           // Custom item type
    itemData: { luckBonus: 0.05 } // Custom data
}
```

{% endcode %}

### custom

For addon-handled rewards. The reward isn't automatically applied.

{% code title="custom reward example" %}

```javascript
rewardType: 'custom',
rewardData: {
    // Your custom data here
}
```

{% endcode %}

## 📁 Categories

| Category   | Description                            |
| ---------- | -------------------------------------- |
| `pets`     | Virtual companions with bonuses        |
| `roles`    | Discord roles (temporary or permanent) |
| `boosters` | Temporary multiplier effects           |
| `titles`   | Display titles for users               |
| `items`    | Generic inventory items                |
| `special`  | Limited edition or seasonal items      |

## 💡 Addon Examples

### Adding Custom Shop Items

{% code title="CustomShopItems.js" expandable="true" %}

```javascript
module.exports = {
    name: 'CustomShopItems',
    
    async run(client) {
        for (const guild of client.guilds.cache.values()) {
            const existing = await global.storeAPI.getItem(guild.id, 'vip-membership');
            if (existing) continue;
            
            await global.storeAPI.addItem(guild.id, {
                itemId: 'vip-membership',
                name: 'VIP Membership',
                description: 'Get exclusive VIP role for 30 days',
                category: 'roles',
                price: 100000,
                maxPerUser: 1,
                rewardType: 'role',
                rewardData: {
                    roleId: 'YOUR_VIP_ROLE_ID',
                    roleDuration: 2592000000  // 30 days
                },
                emoji: '💎',
                featured: true
            });
            
            console.log(`Added VIP item to ${guild.name}`);
        }
    }
};
```

{% endcode %}

### Seasonal/Limited Items

{% code title="SeasonalStore.js" expandable="true" %}

```javascript
module.exports = {
    name: 'SeasonalStore',
    
    async run(client) {
        const month = new Date().getMonth();
        
        // December = Christmas items
        if (month === 11) {
            for (const guild of client.guilds.cache.values()) {
                const existing = await global.storeAPI.getItem(guild.id, 'santa-hat-2024');
                if (existing) continue;
                
                await global.storeAPI.addItem(guild.id, {
                    itemId: 'santa-hat-2024',
                    name: 'Santa Hat 2024',
                    description: 'Limited edition holiday item!',
                    category: 'special',
                    price: 25000,
                    stock: 100,  // Only 100 available!
                    rewardType: 'title',
                    rewardData: { title: '🎅 Santa 2024' },
                    emoji: '🎄',
                    featured: true
                });
            }
        }
    }
};
```

{% endcode %}

### Dynamic Pricing

{% code title="DynamicPricing.js" expandable="true" %}

```javascript
module.exports = {
    name: 'DynamicPricing',
    
    events: {
        'discord:ready': async (eventData, context) => {
            // Update prices every hour based on purchases
            setInterval(async () => {
                for (const guild of context.client.guilds.cache.values()) {
                    const items = await global.storeAPI.getItems(guild.id, 'pets');
                    
                    for (const item of items) {
                        // Increase price if stock is running low
                        if (item.stock > 0 && item.stock < 10) {
                            await global.storeAPI.updateItem(guild.id, item.itemId, {
                                price: Math.floor(item.price * 1.1)
                            });
                        }
                    }
                }
            }, 3600000); // Every hour
        }
    }
};
```

{% endcode %}

### Purchase Announcements

{% code title="PurchaseAnnouncer.js" expandable="true" %}

```javascript
module.exports = {
    name: 'PurchaseAnnouncer',
    
    async run(client) {
        const originalPurchase = global.storeAPI.purchaseItem.bind(global.storeAPI);
        
        global.storeAPI.purchaseItem = async (guildId, userId, itemId, c) => {
            const result = await originalPurchase(guildId, userId, itemId, c);
            
            if (result.success && result.item.metadata?.featured) {
                const guild = client.guilds.cache.get(guildId);
                const channel = guild?.channels.cache.find(
                    ch => ch.name === 'purchases' || ch.name === 'general'
                );
                
                if (channel) {
                    const user = await client.users.fetch(userId);
                    await channel.send(
                        `🎉 **${user.username}** just purchased **${result.item.name}**!`
                    );
                }
            }
            
            return result;
        };
    }
};
```

{% endcode %}

## 📊 Item Schema

Full item object structure:

{% code title="Item Schema" expandable="true" %}

```javascript
{
    itemId: 'uuid-string',
    guildId: 'guild-id',
    name: 'Item Name',
    description: 'Item description',
    category: 'pets',
    price: 50000,
    stock: -1,
    maxPerUser: -1,
    enabled: true,
    rewardType: 'pet',
    rewardData: { ... },
    requirements: {
        level: 0,
        prestige: 0
    },
    metadata: {
        emoji: '🐉',
        color: '#5865F2',
        image: null,
        featured: false,
        sortOrder: 0
    },
    createdAt: Date,
    updatedAt: Date
}
```

{% endcode %}

## 📋 Purchase Record Schema

{% code title="Purchase Record Schema" expandable="true" %}

```javascript
{
    orderId: 'uuid-string',
    guildId: 'guild-id',
    userId: 'user-id',
    itemId: 'item-id',
    itemName: 'Item Name',
    category: 'pets',
    price: 50000,
    rewardType: 'pet',
    rewardData: { ... },
    status: 'completed',
    purchasedAt: Date
}
```

{% endcode %}
