> For the complete documentation index, see [llms.txt](https://developer.vario-software.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.vario-software.de/documentation/apps/faq.md).

# FAQ

## App authentication

### Where does my App get its credentials for a tenant?

VARIO Cloud hands your App an **offlineToken** in the body of the install call. Persist it, keyed by tenant, before doing anything else. Your App exchanges it for short-lived access tokens from then on.

It is **not** a one-time-only event, though: the customer can renew it at any time. In the Admin-Center, on the installed App's page, **"Offline-Token erneuern"** issues a fresh offlineToken and calls your **install endpoint again** with it.

{% hint style="warning" %}
So your install endpoint must be safe to call more than once, and must **overwrite** the stored token rather than keeping the first one. Migrations already behave that way — a step that has run is skipped — but the token write must not be conditional on "no token stored yet".
{% endhint %}

→ [App Authentication](/documentation/apps/authentication.md)

### My App suddenly gets 401 from the API for one tenant. Why?

Most likely the tenant's offlineToken has **expired through inactivity**.

The token is valid for **45 days**, and every use extends it by another 45. So it never expires while the App is working — but **45 consecutive days with no API call for that tenant** invalidate it. Typical victims: seasonal integrations, test tenants, and Apps that only act when a customer triggers something.

Once it has expired, the App instance is flagged accordingly and the customer is prompted in the Admin-Center to use **"Offline-Token erneuern"**, which sends your install endpoint a fresh token. That is a customer action — your App cannot trigger it.

Two things you can do:

* **Prevent it**: if your App can be idle for weeks, make a small scheduled call so the token stays alive.
* **Diagnose it**: fail clearly and log which tenant is affected, so this looks like an expired token rather than a generic outage.

### VARIO calls my App and my App answers 401. What's wrong?

Your App is rejecting the inbound token. It must be verified as:

* an **ES256**-signed JWT,
* against the **JWK set** you received when creating the App,
* with `aud` equal to your `appIdentifier`,
* and a valid `exp`.

## Installation and migrations

### I changed my migration and nothing happened.

Migrations run **once, ever**. Each step is recorded by name, and an already-recorded step is skipped — editing its body has no effect on tenants where it already ran.

Add a **new step with a new name** instead. For steps that must run every time (webhook registration is the classic case), use `always()` rather than `setMigration()`.

### My install reported success but nothing was created.

Migration errors are **caught, not thrown**: they go to your error handler and the app log, and the install still reports success.

Read the app log. Failed steps are not recorded as completed, so they retry on the next install.

### `createSalesChannel` returned an empty object.

That is the platform telling you a **license is missing**. Only the first sales channel is license-free; creating more requires a sales channel license. The framework catches the resulting `402`, logs a warning and returns `{}` so the migration continues — which means your code must tolerate a missing `id`.

### I get a 404 reading an EAV group that I create in the same migration.

Ordering. An EAV group must be created by an **earlier** step before it can be read or changed. The same applies to anything else you look up by identity — a bank cannot reference a backend that doesn't exist yet.

## Manifest, permissions and UI

### What is the complete list of `pointOfIntegration` values?

There intentionally isn't one in this documentation — integration points are added with every release, so any list published here would be wrong within a version or two.

Read them out of your own installation instead:

1. Open the ERP in [support mode](https://help.vario-software.de/support/melden-von-problemen-in-vario-cloud/support-modus).
2. Enable the toggle **"App-Integrationspunkte anzeigen"** ("Show app integration points").
3. Reload when prompted.

Every available integration point is now labelled in the UI with the exact `pointOfIntegration` string to put in your manifest. Navigate to the screen you want to extend and read it off there.

→ [App Manifest](/documentation/apps/app-manifest.md)

### My UI integration doesn't show up.

There is **no manifest validation**, and integration points are matched by exact string comparison — so a typo means your integration silently never appears.

Check:

* the spelling of `pointOfIntegration`;
* that you kept the literal `{APP_IDENTIFIER}` placeholder where the point requires it;
* that the user has the verb named in `permissionKey`.

Integration points are added with every release, so don't work from a list. Open the ERP in [support mode](https://help.vario-software.de/support/melden-von-problemen-in-vario-cloud/support-modus), enable **"App-Integrationspunkte anzeigen"** and reload — the ERP then labels every available integration point with the exact `pointOfIntegration` string to use.

→ [App Manifest](/documentation/apps/app-manifest.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developer.vario-software.de/documentation/apps/faq.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
