# Private modules Source: https://tehoclient.dev/modules/private SDK: 1.0.0 Private modules are for servers Teho has approved, usually partners. They need a **private grant**: a token signed by Teho, bound to your server's hosts, that lists the capabilities and catalogue items you may use. The client checks it against the address the player actually connected to, so a grant cannot be copied to another server. | Capability | What it does | |---|---| | `npc:1` | Dress NPCs in catalogue cosmetics and play emotes on them. | | `statue:1` | Client-side statues of real players, in their own skin and cosmetics. | | `branding:1` | Your accent colour, logo, banner and background on the joining screen, toasts and cards. | | `showcase:1` | Opens Teho's locker preview for catalogue items, for partner shops. | | rewards | Server to backend: grant real catalogue cosmetics within your allowance. | **No server-made cosmetics** None of these create cosmetics. Partnered cosmetics are ordinary items in the Teho catalogue, sold on the Teho store, so NPCs, statues and rewards can only use items that already exist and that your grant lists. Cosmetic files never pass through your server; each client fetches them through its own Teho session. ## Install the grant ```yaml private: grant: "eyJibG9iIjoi…" ``` On Minestom, use `TehoMinestom.builder().privateGrant(token)`. `TehoPlayer.privileges()` lists what the grant unlocked for a player, `privilegeError()` explains a refusal, and `TehoListener.onPrivileges` fires when the check completes. ## NPC cosmetics NPCs are your server's own fake players. Teho can dress them in catalogue cosmetics and make them emote, for every viewer. ```java NpcApi npcs = TehoApi.get().npcs(); npcs.look(shopkeeper, NpcLook.wearing() .cape("founder_cape") .wings("founder_wings") .build()); npcs.playLooped(shopkeeper, "wave"); npcs.mirrorViewer(mirror); npcs.playOnce(greeter, "bow"); ``` `NpcLook.wearing()` has `cape`, `headwear`, `wings`, `bodywear`, `pet`, `companion` and `trail`, plus `cosmetic(slot, id)` and `cosmetic("slot:id")`. `mirrorViewer` shows each viewer their **own** equipped cosmetics on the NPC, and your server never learns what they wear. | Method | What it does | |---|---| | `look(npc, NpcLook)`, `clearLook(npc)` | Sets or clears what it wears. | | `emote(npc, NpcEmote)`, `playLooped`, `playOnce` | Plays an emote. | | `stopEmote(npc)`, `resetEmote(npc)` | Stops it, or returns to idle. | | `remove(npc)`, `clear()` | Forgets one NPC, or all of them. | | `looks()`, `emotes()` | What is set now. | State is remembered and replayed to everyone who joins. NPCs can never be real players and cannot wear badges. ```yaml npcs: - uuid: "1f5c2b3a-0000-2000-8000-000000000001" look: [cape:founder_cape, wings:founder_wings] emote: wave loop: true - uuid: "1f5c2b3a-0000-2000-8000-000000000002" mirror: true ``` ## Statues A statue is a client-side figure of a real player, in their real skin and their real cosmetics, for halls of fame and leaderboards. ```java TehoApi.get().statues().place(Statue.of("champion", championId, "Alex") .at(0.5, 70, 12.5, 180) .pose(Statue.Pose.TROPHY) .scale(1.5) .label("§6Season 4 champion") .dimension("overworld") .build()); TehoApi.get().statues().remove("champion"); ``` Poses are `STAND`, `WAVE`, `SALUTE`, `SIT` and `TROPHY`, and `emote(id)` plays an emote on the statue. ## Branding ```java AssetStore assets = TehoApi.get().assets(); TehoApi.get().branding().apply(Branding.builder(0x4DA9FF) .logo(assets.load(Asset.Kind.PNG, folder.resolve("logo.png"))) .banner(assets.load(Asset.Kind.PNG, folder.resolve("banner.png"))) .tagline("Ranked duels since 2019") .build()); TehoApi.get().branding().apply(Branding.reset()); ``` ## Showcase Opens Teho's own locker preview with the items you list, for partner shops that sell catalogue cosmetics. ```java teho.showcase().open("Skyline collection", "Available on the Teho store", Arrays.asList("cape:skyline_cape", "wings:skyline_wings"), "wave", "cape:skyline_cape"); ``` ## Rewards Grant a real catalogue cosmetic to a player, within the per-item allowance on your grant. Every grant is written to an audit log. ```java RewardsApi rewards = TehoApi.get().rewards(); if (rewards.enabled()) { rewards.grant(winnerId, "cape:skyline_cup_2026", "Won the Skyline Cup").thenAccept(result -> { if (!result.granted()) { getLogger().warning("Reward failed: " + result.error()); } else { getLogger().info(result.remaining() + " grants of " + result.item() + " left"); } }); } ``` Items are `slot:id` catalogue ids, and badges can never be granted. Rewards need `backend.key` set, since they go from your server to the Teho backend.