> ## Documentation Index
> Fetch the complete documentation index at: https://takeprofit.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Invite-only Indicators

Keep selling your indicator where you already sell it — Whop, Stripe, Discord, Patreon, Gumroad or your own site. When someone pays, your checkout calls the **Access Grants API** with the buyer's TakeProfit username, and the indicator appears in their Favorites and runs on their charts until the date you set.

You keep your payment provider, your pricing, your bundles and your customer list. TakeProfit only handles the access.

The Marketplace price slider caps at \$100, but that cap only applies to sales made here. There is no cap on what you charge on your own checkout.

## How it works

1. The buyer creates a TakeProfit account and gives you their **username** at checkout.
2. Your payment platform confirms the purchase — a webhook, a Zapier trigger or a CSV export.
3. You call the API with that username and an end date.
4. The buyer opens the platform and finds the indicator under the **Invited** filter in the indicator panel, and in their Favorites.
5. Renewals extend the date with the same call. Refunds remove access, or you let the date pass.

| Rule | What it means |
| - | - |
| **Paid indicators only** | For now a grant works only on a paid indicator that is published on the Marketplace. On a free one the call fails with `product_not_found` and the message `Product with id <id> does not exist`. |
| **Subscription or grant** | A user can run a paid indicator if they bought it on the Marketplace **or** you granted them access. Either one is enough. |
| **End date** | Every grant carries an `expiresAt` date in UTC. Access ends automatically at that moment. |
| **No end date** | `expiresAt: null` grants access that does not expire, for lifetime deals. |
| **Repeat calls extend** | Calling `PUT` again for the same user replaces the end date rather than adding a second grant, so retries are safe. |
| **Revoke anytime** | `DELETE` removes access immediately, for refunds and chargebacks. |
| **Favorites** | A new grant adds the indicator to the buyer's Favorites, the same way a Marketplace purchase does. It stays in their Favorites after access ends, but no longer runs. |

Your indicator stays listed on the Marketplace. Anyone can still find it and buy it there at your price. Grants are just another way in, for buyers who paid you directly.

One buyer can hold both. If someone already bought on the Marketplace, you can still grant them access on top of it — the two are independent, and either one on its own lets them use the indicator. While a grant is active and there is no subscription, the product page shows **Access granted** instead of a Subscribe button, so they cannot buy a subscription until the grant ends. A buyer who does hold an active subscription sees that subscription as usual.

## What the buyer sees

Granted access looks almost the same as a subscription — the indicator is simply usable.

* **In the indicator panel** the script sits under the **Invited** filter, next to Subscribed, and its card has **Add to chart** on it rather than a padlock and a price. It is in their Favorites as well.
* **The card shows no end date.** If your automation extends access on every charge the date keeps moving, so showing one would only mislead. Subscribed cards don't show a renewal date either.
* **On the product page** the buyer block reads **Access granted**, with **Managed by the author** below it and the end date if the grant has one. There is no Subscribe button and no Manage Subscriptions link, because the subscription is not with TakeProfit.
* **When access ends** the product page goes back to showing your price and a **Subscribe** button, so the buyer can subscribe here instead if they want to.

## Set up invite-only access

**1. Publish the indicator**

Publish it on the Marketplace as described in [How to publish an indicator](https://takeprofit.com/docs/guide/monetization-tools/Sell-your-indicators.md#how-to-publish-an-indicator) and wait for approval. Review takes up to 2–4 business days, so plan launches around it.

**2. Copy the product ID**

Open your indicator's publication page or its product page. As the owner you see its **Product ID** — copy it.

> [!NOTE]
>
> Use the **product** ID, not the indicator ID. The product ID does not change when you publish a new version of the indicator, so automations built on it keep working.

**3. Create an API token**

Go to **Settings → Login & Security → Personal API Tokens**, the same place you create a Market Data API token, and click **Generate New Token**. Name it after where you will use it, for example `whop-webhook`, and give it the indicator access scopes:

* `indicator:access:write` — grant, extend and revoke access
* `indicator:all:read` — list who has access

Copy the token straight away. It is shown only once. See [Personal API Tokens](https://takeprofit.com/docs/guide/getting-started/mfa.md#personal-api-tokens) for how tokens are managed and revoked.

> [!WARNING]
>
> Tokens need an active paid plan. Without a subscription the block shows **Upgrade Plan and Generate** instead of the generate button. If your subscription ends, every token you hold is revoked — which stops your grants automation until you subscribe again and generate a new one.

**4. Test your setup**

Check it works before you automate it. Grant access to a teammate, or to one of your own test accounts:

```bash theme={null}
export TP_API_KEY="your-token"
export TP_PRODUCT_ID="your-product-id"
export TP_USERNAME="buyer-username"

curl -X PUT \
  "https://takeprofit.com/api/marketplace/indicators/$TP_PRODUCT_ID/grants/$TP_USERNAME" \
  -H "x-api-key: $TP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "expiresAt": "2026-12-31T00:00:00Z" }'
```

A response with `"success": true` means your token, its scopes and the product ID all work, and the indicator is now in that account's Favorites. Fix any errors here, before you add your payment platform — [Errors](#errors) below says what each failure means.

**5. Automate it**

Let your payment platform make the call on every sale, renewal and refund. Anything that can send an HTTP request when a payment completes will do — a webhook from Whop, Stripe, Discord, Patreon or Gumroad, a no-code step in Zapier, Make or n8n, or a script run against a CSV export of your buyers.

They all need the same three things: the buyer's TakeProfit username, your product ID, and your token in the `x-api-key` header.

## Access Grants API

**Base URL:** `https://takeprofit.com/api/marketplace`

Send your API token in the `x-api-key` header on every call. Every date — the `expiresAt` you set, and the timestamps that come back — is ISO 8601 in UTC, like `2026-12-31T00:00:00Z`.

| Path parameter | What it is |
| - | - |
| `productId` | The product ID, not the indicator ID. Shown on the product page to its owner. |
| `username` | The buyer's TakeProfit username. The API grants access to whatever username you send, so check it before you send it. |

### Grant or extend access

```
PUT /api/marketplace/indicators/{productId}/grants/{username}
```

Grants access, or updates `expiresAt` if the user already has it.

Request body:

```json theme={null}
{ "expiresAt": "2026-12-31T00:00:00Z" }
```

Response:

```json theme={null}
{
  "success": true,
  "data": {
    "productId": "21bd6f72-408c-4e03-a609-2a0341911ace",
    "username": "john",
    "expiresAt": "2026-12-31T00:00:00Z",
    "createdAt": "2026-10-13T10:00:00Z",
    "updatedAt": "2026-10-13T10:00:00Z"
  }
}
```

### Remove access

```
DELETE /api/marketplace/indicators/{productId}/grants/{username}
```

```json theme={null}
{ "success": true }
```

### List who has access

```
GET /api/marketplace/indicators/{productId}/grants
```

Returns the active buyers of the product. A `null` `expiresAt` is a grant with no end date.

```json theme={null}
{
  "success": true,
  "data": {
    "items": [
      {
        "username": "john",
        "expiresAt": "2026-12-31T00:00:00Z",
        "createdAt": "2026-10-13T10:00:00Z",
        "updatedAt": "2026-10-13T10:00:00Z"
      },
      {
        "username": "anna",
        "expiresAt": null,
        "createdAt": "2026-10-12T09:00:00Z",
        "updatedAt": "2026-10-12T09:00:00Z"
      }
    ]
  }
}
```

## Errors

A failed call returns an HTTP status and a code you can switch on in your automation.

| Status | Code | What it means |
| - | - | - |
| `400` | `schema_error` | The request is malformed. Either `expiresAt` is absent, is not ISO 8601, or is in the past — send `null` rather than omitting the field when you want access that does not expire — or the username itself is invalid. |
| `401` | `invalid_api_key` | The key is missing, revoked or unknown, or it has gone over its request limit. |
| `403` | `missing_scope` | The token does not carry the scope the call needs. |
| `403` | `not_product_owner` | The product exists, but you are not its owner. |
| `404` | `product_not_found` | There is no active paid indicator with this ID. The indicator has to be both paid and published — grants do not work on free ones yet. |
| `404` | `user_not_found` | The username is not registered on TakeProfit. |

The two you are most likely to hit in production are `user_not_found`, when a buyer gave you a username they never signed up with, and `schema_error` on a date your automation built in the wrong format or in the past. Handle those two at the checkout end and the rest are setup mistakes you will catch while testing.

## Who does what

| Task | Owner |
| - | - |
| Selling, payments, refunds | You |
| Collecting the buyer's TakeProfit username | You |
| Checking that the buyer has a TakeProfit account | You and the buyer |
| Calling the API from your automation | You |
| Authenticating calls and checking that you own the indicator | TakeProfit |
| Granting, extending, expiring and revoking access | TakeProfit |
| Adding the indicator to the buyer's Favorites | TakeProfit |

## Moving buyers from another platform

The API finds a buyer by **username**. So before you can move a list across, you need everyone's TakeProfit username — not their email, and not their handle on the platform you sold through.

* **Ask for the username, not the email.** Collect it at checkout, and tell buyers it is the one they signed up with here.
* **Usernames are not reserved across platforms.** Someone coming from TradingView will usually want the same handle, but it may already be taken here. Tell them to claim it before you launch.
* **One user per call.** To move a list across, loop over it and call `PUT` once per username.

## Good to know

* **The buyer must sign up first.** A grant needs a username that already exists, so send buyers to sign up before you grant them anything.
* **Keep your token on a server.** Never put it in a web page, a browser extension or a public repository. Anyone holding it can change access to your indicators.
* **Access is checked as subscription or grant.** Granting access to someone who already subscribed does no harm, and removing a grant does not cancel a subscription.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.