# Plans and AI features (/plans)



inklet authorizes every SDK request against the current plan of the user who
owns the personal access token. A valid PAT proves who the caller is; the plan
decides which processing features that user can run.

| SDK capability                                                     | Free | Pro | Uses inklet AI |
| ------------------------------------------------------------------ | ---- | --- | -------------- |
| Read Displays, Contents, Presentations, queues, and current frames | Yes  | Yes | No             |
| Hardcode Push                                                      | Yes  | Yes | No             |
| Auto Push                                                          | No   | Yes | Yes            |
| Manual Push                                                        | No   | Yes | Yes            |

Manual Push still requires Pro. Choosing the Display yourself skips automatic
routing, but inklet still fetches, understands, summarizes, and lays out the
assets. Hardcode Push receives a finished PNG or JPEG and only scales it to the
Display output size, so it remains available on Free.

## Authorization failures [#authorization-failures]

Auto or Manual Push on Free fails with `SubscriptionRequiredError`:

```ts
import { SubscriptionRequiredError } from "@inklethq/sdk";

try {
  await inklet.push.auto({ assets });
} catch (error) {
  if (error instanceof SubscriptionRequiredError) {
    console.error(error.code); // "subscription_required"
    console.error(error.requestId);
    console.error(error.details);
  }
}
```

The error extends `PermissionDeniedError`. It is not transient: do not retry
until the subscription changes. The backend may include `currentPlan`,
`requiredPlan`, and `feature` in `details`; treat `details` as structured
diagnostic context rather than UI copy.

<Callout>
  Upgrade or manage the subscription in the
  [inklet portal](https://portal.iminklet.com/subscription). The SDK does not
  create checkout sessions, open the billing portal, list invoices, or expose
  payment-provider identifiers.
</Callout>

## After an upgrade [#after-an-upgrade]

You do not need to issue a new PAT. Authorization uses the token owner's
current server-side plan on each request, so retry the operation with the same
client after the plan change is active.

The plan check is enforced by the inklet service for both `inklet.push.*` and
the lower-level Content endpoints. Calling `contents.create()` directly does
not bypass it.
