1DE1DEDeveloper Hub
Developer Docs

Build MiniApps for the SuperApp.

Everything you need: Silent SSO with no login screen, container control, deep links, the platform APIs for chat, signature & payment — and an MCP server that lets your AI agent get going right away.

Introduction — SuperApp & MiniApps

The KOBIL SuperApp is a native container (a mobile app). Individual features — appointment booking, AI chat, dealings with public authorities — are MiniApps: standalone web apps that run in a WebView inside the SuperApp.

┌─────────────────────────────────────┐ │ KOBIL SuperApp (native container) │ │ ┌────────────────────────────────┐ │ │ │ WebView │ │ ← loads your MiniApp URL │ │ ┌──────────────────────────┐ │ │ ← reads miniApp.json │ │ │ Your MiniApp (Next.js) │ │ │ ← cookie injection → Silent SSO │ │ └──────────────────────────┘ │ │ │ └────────────────────────────────┘ │ │ native tab bar (always visible) │ └─────────────────────────────────────┘

For the end user it feels native:

  • Sign-in without typing — the user is signed in to the SuperApp and your MiniApp takes over their identity automatically (Silent SSO).
  • System UI controlled by the container — the SuperApp controls full-screen mode, status bar color and navigation via your miniApp.json.
  • Overlay navigation — your MiniApp can open another one via a deep link.
All MiniApps in one environment share the same identity provider → the same OIDC sub per user across every app. Cross-app features build on this.

Quickstart — your first MiniApp in 5 minutes

Register

Create an account in the Partner Hub (email + password).

Create a MiniApp

Enter a URL + name in the dashboard. We register it as an OIDC service and publish it in the store. You receive your service ID (= sID = OIDC client_id) and a client_secret.

Grab the code starter

Open the pre-filled docs in the dashboard or use MCP scaffold_miniapp.env and the OIDC flow come filled in with your values.

Deploy

Host your web app at the MiniApp URL you specified.

Open it in the SuperApp

Silent SSO runs automatically — no login screen.

Don't want to click through it yourself? Connect your AI agent via MCP (see below) and let it handle all of this.

miniApp.json — container control

A static file in your web root: public/miniApp.json (→ /miniApp.json). The SuperApp reads it when your MiniApp loads.

// public/miniApp.json
{
  "version": "2.0",
  "fullScreen": true,
  "theme": "app-default",
  "statusBar": { "theme": { "light": { "backgroundColor": "#ffffff" }, "dark": { "backgroundColor": "#ffffff" } } },
  "navigationBar": { "visible": false, "theme": { "light": { "backgroundColor": "#ffffff" }, "dark": { "backgroundColor": "#ffffff" } } }
}
FieldMeaning
fullScreentrue = the MiniApp draws all the way under the status bar (full screen).
themeapp-default adopts the SuperApp theme.
navigationBar.visiblefalse = no container navigation; you build the UI yourself.
statusBar.themeStatus bar color per light/dark mode.
Design consequence: the status bar & native tab bar are white. Keep the top safe-area region clear (no header right at the top) and extend your background color into it accordingly.

Design & Native Feel

With fullScreen: true, your MiniApp draws from the very top (under the status bar) all the way to the bottom. But the native SuperApp menu sits on top of your web UI: a floating pill in the top right with two buttons — Options (grid ⊞) and Close (✕). That area belongs to the SuperApp — you must keep it clear.

┌───────────────────────────────────────────┐ │ 14:48 📶 ▢ 🔋 │ ← system status bar (safe area) │ │ │ Survey ┌ ⊞ │ ✕ ┐ │ ← NATIVE pill: Options + Close │ ╰─ free to use on the left ─╯ └─ KEEP CLEAR ┘ │ │ │ your MiniApp · full screen │ │ (mobile-first, native feel) │ │ │ │ ▁▁▁ ✓ Surveys ◌ Profile ▽ Awards ▁▁▁ │ ← your own bottom tab bar (native style) └───────────────────────────────────────────┘
Reserve the top right: plan for ~128 px wide × 52 px tall (below the status bar) to stay completely clear. Place no tappable or important elements there — otherwise they disappear under the native pill. Never build your own close/back button in the top right — the SuperApp handles that.
Actively using the space to its left looks the most polished: a screen title or logo in the top left (like “Survey” in the example) fills out the header and makes the native pill on the right feel like a natural part of the app.

Safe areas & the reserved zone — how to do it

Enable viewport-fit=cover and use the env() safe-area insets. Keep space for the pill clear in the top right.

<!-- Safe-Areas (viewport-fit) + ALLE Zoom-Arten aus -->
<meta name="viewport"
      content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1, user-scalable=no">

Disable every kind of zoom (required for a native feel)

Nothing gives a web app away faster than zoomable content. There are three sources of zoom — turn them all off:

Type of zoomDisable with
Pinch-to-zoom (two fingers)maximum-scale=1, user-scalable=no in the viewport meta (see above). The SuperApp WebView respects this.
Double-tap zoomtouch-action: manipulation (globally, e.g. on html).
Auto-zoom on focusing an input/selectField font size ≥ 16px — otherwise iOS zooms in automatically when tapped.
/* gegen Doppeltipp-Zoom; Eingaben nie unter 16px */
html{ touch-action: manipulation; -webkit-text-size-adjust: 100%; }
input, select, textarea{ font-size: 16px; }
The viewport meta covers pinch & double-tap zoom inside the container; the 16px rule is still needed, because focus auto-zoom kicks in independently of it. For extra safety against iOS gestures: document.addEventListener('gesturestart', e => e.preventDefault()).

Native feel — the must-do checklist

The MiniApp has to feel like a native screen, not like a website in a browser. Mobile-first (design for 360–430 px width first):

TopicRule
Height100svh/100dvh instead of 100vh — otherwise the layout jumps with the address bar.
Touch targetsAt least 44×44 px for anything tappable.
TypeSystem stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif.
No hoverNo hover-only UI — touch has no hover. Use clear :active states for instant feedback.
ZoomAll three kinds of zoom off (pinch, double-tap, focus auto-zoom) — see the section above. Plus touch-action: manipulation also kills the 300 ms tap delay.
ScrollMomentum scrolling, overscroll-behavior: contain against “pull-through”. No horizontal overflow wobble.
Selectionuser-select: none on buttons/nav; allow text selection only where it makes sense.
NavigationNative patterns: a bottom tab bar (with safe-area-inset-bottom), bottom sheets instead of desktop modals, swipe where it fits.
MotionShort, soft transitions (cubic-bezier(.2,.8,.2,1)), no layout shifts. Optimistic UI + skeletons instead of spinners.
ColorThe status bar & tab bar are white (miniApp.json) → resolve top/bottom into white; respect prefers-color-scheme.
Rule of thumb: would your screen pass as an App Store screenshot? Tab bar at the bottom, title in the top left, cards with soft shadows, large tap areas, instant feedback — then it feels native.

Authentication — Silent SSO (OIDC + PKCE)

Your MiniApp authenticates via Authorization Code + PKCE (confidential client) against the KOBIL IDP. Because the SuperApp injects the Keycloak session, this happens with no login screen.

Silent SSO ONLY works inside the SuperApp. If you just open the MiniApp URL in a normal browser, there is no automatic sign-in — the IDP finds no injected session and the login fails or ends up in an infinite loop. To test in a browser you need WebFlow mode + the test account (see Deploy → Test in the browser).

The flow

  1. No user_session cookie → redirect to /api/auth/login?next=<path>.
  2. /api/auth/login: generates state, nonce, the PKCE verifier, stores them in a short-lived oidc_tx cookie (HttpOnly, 10 min) and redirects to the authorization_endpoint (code_challenge=S256).
  3. IDP → Silent SSO → redirect to /api/auth/callback?code=…&state=….
  4. /api/auth/callback: checks state, exchanges the code (with client_secret + code_verifier), verifies the id_token via JWKS, extracts claims and sets your own signed user_session cookie.
  5. Follow-up requests only check the user_session cookie (no IDP round-trip).
// PKCE + Authorize-URL
import { createHash, randomBytes } from "crypto";

export function pkce() {
  const verifier = randomBytes(32).toString("base64url");
  const challenge = createHash("sha256").update(verifier).digest("base64url");
  return { verifier, challenge };
}

export function authUrl(state, nonce, challenge) {
  const p = new URLSearchParams({
    client_id: process.env.OIDC_CLIENT_ID, response_type: "code",
    scope: "openid profile email", redirect_uri: BASE + "/api/auth/callback",
    state, nonce, code_challenge: challenge, code_challenge_method: "S256",
  });
  return ISSUER + "/protocol/openid-connect/auth?" + p;
}
CookieContents · TTL · Flags
oidc_txstate/nonce/PKCE verifier · 10 min · HttpOnly, SameSite=Lax
user_sessionsigned claims (sub, name, …) · e.g. 8 h · HttpOnly, SameSite=Lax
SameSite=Lax is required. The redirect back from the IDP is cross-site — Strict would block your cookies.
Dev fallback: if OIDC_CLIENT_ID is not set locally, skip the OIDC layer (sub = "dev-user") — that way you develop without an IDP.

mPower — Basics & Authentication

mPower is the platform's server-to-server interface. With it, your backend sends messages into the citizen's SuperApp chat, has them tap buttons, sign PDFs and trigger payments — all without the citizen logging in anywhere separately. The following sections (Chat & Choice, PDF Signature, Payment) all build on these basics.

Two APIs, two clients, one realm

There are two separate APIs. Chat, choice & signature run over your regular OIDC client; payment runs over a dedicated merchant client. Don't mix the two up — that's the most common source of errors.

APIWhat forClient
mPower (mercury)Chat, choice messages, PDF signature, mediayour OIDC client (sID + client_secret)
Payment (mpay-merchant)Trigger a payment + statusseparate merchant client (its own merchantId + secret + tenantId)
Your sID, your client_secret and all endpoint URLs come pre-filled in the dashboard. You receive the merchant credentials for payment separately from your 1DE contact.

Step 1: get an access token (client_credentials)

Both APIs authenticate via client_credentials against the same token endpoint of the realm. The token is valid for ~300 seconds — fetch it once and cache it instead of requesting a new one on every call.

# Token fuer mPower (mit deinem OIDC-Client)
curl -X POST "<ISSUER>/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=<DEINE_SID>" \
  -d "client_secret=<DEIN_CLIENT_SECRET>"
# → { "access_token": "eyJ…", "expires_in": 300, … }

Key terms

TermMeaning
userIdThe citizen's OIDC sub — exactly the value you get at sign-in from user_session or /api/auth/me. No login needed (S2S).
serviceUuidYour sID — identifies your service as the sender.
versionSchema version of the mPower message. Currently 3.
{tenant}The realm/tenant in the URL (for mPower, the same as your OIDC realm).

The callback model (very important)

Outgoing calls (you → platform) get a small receipt { messageId, instanceId } back immediately. The citizen's actual response (they signed, tapped a button, typed something) arrives asynchronously as a callback.

  • One global service callback URL (configured in your service config) receives ALL mPower callbacks for your service — signature, choice and chat all land at the same endpoint. You tell them apart via messageType.
  • Payment has its own callback (merchantCallback), which you pass per transaction.
mPower does NOT echo your query parameters back in the callback. If you append ?applicationId=… to the callbackUrl, it comes back empty. So correlate via the file name you chose (for signature) or via from.userId + internal status. The payment callback, by contrast, does echo the query param.

Chat & Choice Messages

With two message types you reach the citizen directly in the SuperApp chat: plain text (processChatMessage) and a choice with buttons (choiceRequest). Both go to the same endpoint:

# Authorization: Bearer <access_token> (siehe Grundlagen)
POST <MPOWER_BASE>/auth/realms/<TENANT>/mpower/v1/users/{userId}/message

Plain-text message

A simple text message that appears in the chat — e.g. a confirmation.

{
  "serviceUuid": "<DEINE_SID>",
  "messageType": "processChatMessage",
  "version": 3,
  "messageContent": { "messageText": "Danke! Dein Antrag ist eingegangen." }
}

Choice message (buttons)

Shows the citizen tappable buttons. Their tap comes back as a choiceResponse callback.

{
  "serviceUuid": "<DEINE_SID>",
  "messageType": "choiceRequest",
  "version": 3,
  "messageContent": {
    "messageText": "Möchtest du jetzt bezahlen?",
    "choices": [{ "text": "Bezahlen" }, { "text": "Später" }]
  }
}

The callback (citizen responds)

When the citizen taps or types, the platform calls your global service callback URL. Envelope:

{
  "message": {
    "content": {
      "messageType": "choiceResponse",         // oder "processChatMessage"
      "messageContent": { "messageText": "Bezahlen" }  // gewählter Button-Text
    },
    "from": { "ecoId": "<TENANT>", "userId": "<sub>" },
    "messageId": "…"
  }
}
messageTypeMeaning
choiceResponsemessageContent.messageText = the button text the citizen chose.
processChatMessageNormal chat text from the user (often simply ignorable).
Correlate the response via from.userId + your internal status (e.g. “this user is waiting on a payment decision”). Buttons have no ID — you recognize the choice only from the messageText.

PDF Signature

You send a PDF to the platform, the citizen signs it directly in the SuperApp, and you get the signed PDF back. The flow in four steps:

Prepare & send the PDF

Fill/flatten the PDF, specify the signature box as percentage coordinates, post it to /signature.

Citizen signs

The SuperApp shows the PDF with the signature field. The citizen signs.

signatureResponse callback

You receive signatureStatus: "signed" + a mediaId.

Download the signed PDF

Use the mediaId to download the finished PDF and process it further.

Step 1 — signature request

A multipart/form-data POST with two parts: signatureFile (the PDF) and signatureData (a JSON string).

POST <MPOWER_BASE>/auth/realms/<TENANT>/mpower/v1/users/{userId}/signature
# Content-Type: multipart/form-data; Authorization: Bearer <token>

# Part "signatureData" (JSON-String):
{
  "version": 3,
  "pageNumber": 1,
  "bottomLeftXCoordinate": 12,
  "bottomLeftYCoordinate": 3,
  "topRightXCoordinate": 39,
  "topRightYCoordinate": 5,
  "serviceUuid": "<DEINE_SID>",
  "messageText": "Bitte unterschreiben",
  "callbackUrl": "https://deine-app.de/api/webhooks/mpower-signature"
}
# → Antwort: { "messageId": "…", "instanceId": "…" }

⚠️ Understanding the coordinates (most common mistake)

The four coordinates are integer PERCENTAGES (0–100) of the page size, with the origin at the bottom leftNOT PDF points and not pixels. If you pass point values (e.g. 200), they are read as 200% → clamped to the edge, and the box disappears. Floats (e.g. 12.5) cause HTTP 400 (the field is an i32). Always round.
FieldMeaning
pageNumberThe page that gets signed (1-based).
bottomLeftX / YBottom-left corner of the signature box, in % of the page (from the bottom left).
topRightX / YTop-right corner, in % of the page.

Converting millimeters to percent (PDF point = 1/72 inch, 1 inch = 25.4 mm):

// X / Breite — direkt von links:
const MM = 72 / 25.4;                       // mm → pt
const pctX = Math.round(mmVonLinks * MM / seiteBreitePt * 100);

// Y — Ursprung ist UNTEN, also von oben umrechnen:
const pctY = Math.round((seiteHoehePt - mmVonOben * MM) / seiteHoehePt * 100);
The AcroForm trap: for form PDFs, flatten() is not enough — it leaves an empty AcroForm dictionary behind, and mPower then shows no signature box (and the form widgets cover your overlay text). Fix: flatten first, then copy the pages into a fresh PDFDocument — that removes the AcroForm completely.

Step 3 — signatureResponse callback

{
  "message": {
    "content": {
      "messageType": "signatureResponse",
      "signatureStatus": "signed",
      "mediaContent": { "mediaId": "…", "fileName": "…",
                         "fileSize": 12345, "contentType": "application/pdf" }
    },
    "from": { "ecoId": "<TENANT>", "userId": "<sub>" }
  }
}
Correlation: since query params are not echoed, give the PDF a meaningful file name when you send it (e.g. <templateId>-<antragId>.pdf) — via mediaContent.fileName or from.userId you can find the request again.

Step 4 — download the signed PDF

GET <MPOWER_BASE>/v1/mpower/tenants/<TENANT>/media/{mediaId}/download
# Authorization: Bearer <token>
# → 301 Redirect auf eine presigned S3-URL.
The download responds with 301 to a presigned S3 URL. fetch follows the redirect automatically and strips the Authorization header cross-origin in the process (as the Fetch spec requires) — S3 authorizes via the signature in the URL. You don't need to do anything special, just allow the redirect.

Payment

Payment triggers a real payment. It runs over a dedicated merchant client — not over your OIDC client. You fetch the token the same way via client_credentials (see Basics), but with the merchant credentials.

THE most important payment rule: merchantId === merchantServiceUUID === the client_id of your payment merchant client — both fields get the same value, and that is NOT the OIDC sID of this MiniApp, but the separate payment client (credentials from 1DE). tenantId = the tenant of your merchant credentials, not the mPower tenant.

Step 1 — start a transaction

POST <PAYMENT_BASE>/mpay-merchant/create/transaction
# Authorization: Bearer <merchant_token>
{
  "version": 1,
  "idempotencyId": "<UUID>",            // echte UUID, gegen Doppelzahlung
  "userId": "<sub>",
  "merchantId": "<MERCHANT_ID>",
  "merchantServiceUUID": "<MERCHANT_ID>",
  "merchantName": "Stadt-Service",
  "merchantCallback": "https://deine-app.de/api/webhooks/payment?applicationId=42",
  "transactionTimeout": 10,
  "amount": 1000,                       // 10,00 € — in CENT (Ganzzahl!)
  "tenantId": "<MERCHANT_TENANT>",
  "currency": "EUR",
  "paymentContent": [[{ "key": "Antrag", "value": "10,00 €" }]]
}
FieldWatch out
amountIn cents, as an integer. €10.00 = 1000. Never a decimal.
idempotencyIdA real UUID. Protects against double-charging on retries.
merchantCallbackYour webhook for the result. Query params are echoed here (unlike with mPower).

Step 2 — result callback

The result arrives asynchronously at your merchantCallback URL once the citizen has paid (or cancelled).

{
  "transactionId": "…",
  "status": "finished",
  "transactionStatus": "finished",
  "message": "Payment complete.",
  "cardGatewayType": "credit_stripe"
}
Success = the status contains finished or completenot “success” or “paid” (this is empirically verified). So check for finished/complete, not for other words.

End to end: form → signature → payment

Here is how the three mPower parts mesh together in a typical public-authority flow:

Fill out the form └─ fill PDF → signature coordinates (%) → mPower /signature (Signature section) ↓ citizen signs in the SuperApp signatureResponse callback "signed" → load mediaId via /media/download ↓ status: awaiting_payment mPower choiceRequest "Pay" (Chat section) ↓ citizen taps "Pay" choiceResponse callback "Pay" → Payment create/transaction (Payment section) ↓ citizen pays Payment webhook status "finished" → done (e.g. letter + "Thanks" in the chat)

A proven state machine for it:

draft → ready → awaiting_signature → awaiting_payment → paying → sent

Discovery — Store & Findability

When you create it, your MiniApp is registered as a service. Two flags control its visibility:

  • searchable — findable in the store.
  • webFlowEnabled — WebFlow active.

Via the sID, your MiniApp is reachable by deep link from other MiniApps and from the SuperApp's AI agent.

Deploy & Domain

Your MiniApp is a normal web app — host it wherever you like (Vercel, your own server, a container …). Required:

Serve miniApp.json

Reachable at /miniApp.json.

Register the redirect URI with the IDP

https://<your-domain>/api/auth/callback. Set when you create the app; re-register it if you change domains, otherwise the OIDC callback fails.

Don't cache the home page

no-store — otherwise the user only sees updates after force-closing the SuperApp.

Need a *.temmuz.uk subdomain (Cloudflare, proxied)? Ask your 1DE contact.

Auto-deploy to your own subdomain (the easiest path)

You don't have to host it yourself at all: upload your project as a ZIP — in the dashboard on your MiniApp, or via the MCP tool deploy_miniapp. We build it as a dedicated container and put it live at <name>-<code>.temmuz.uk (with HTTPS).

Zip the project

Next.js or static. package.json at the root, without node_modules, .next, .git (the server builds it). Max. 25 MB.

Upload

Dashboard → MiniApp → “Upload & deploy ZIP”, or agent: deploy_miniapp({ service_id, zip_base64 }).

Done

After a 1–3 min build your MiniApp is live at the subdomain.

Updating = just deploy again. For changes you upload the same project again (dashboard) or call deploy_miniapp with the same service_id — same subdomain, the container is replaced. Do NOT create a new MiniApp for this (otherwise you get duplicates). create_miniapp is only needed once per app.
For a standard Next.js app we automatically generate a Dockerfile (npm installnext buildnext start). If your ZIP has its own Dockerfile, we use yours. No package.json → it's served as a static site.

Test in the browser (WebFlow)

Opening the bare subdomain in a browser is NOT enough. Without WebFlow the login fails (Silent SSO only exists inside the SuperApp). To test in a browser you have to enable WebFlow and sign in with the test account:

Inside the SuperApp, sign-in runs via Silent SSO automatically. To test outside the SuperApp (in a normal browser):

Enable WebFlow

Set the “WebFlow active” switch when you create the app (dashboard) — then web login is possible.

Open the subdomain & sign in

On the IDP login page, sign in with the test account:

Test IDP accountValue
Emailhello@kobil.com
PasswordTestAccount57428
Turn WebFlow off again after testing! In SuperApp operation WebFlow must be off for the Silent SSO flow to work. (Note: toggling this on an existing service after the fact is currently only reliable via the SmartDashboard UI or at creation time — an API automation for it is coming.)

MCP for AI agents

Connect your AI agent (Claude, Cursor, …) directly so it develops against your real MiniApp config right away — read the docs, fetch the config, generate code, even create new MiniApps.

ToolEffect
get_docsThese docs (optional: just one section).
list_my_miniappsYour MiniApps.
get_miniapp_configOIDC config, client_secret, redirect URIs, deep link, miniApp.json, .env, endpoints.
scaffold_miniappReady-made starter files (Next.js), prefilled.
create_miniappCreate & publish a new MiniApp (optionally with a logo data URI).
deploy_miniappHost a project (Next.js/static) as a dedicated container on a subdomain (ZIP base64).
delete_miniappDelete your own MiniApp & publish the change.

Connection details

FieldValue
Endpointhttps://deutschlandappwebpage.temmuz.uk/mcp
TransportStreamable HTTP
Auth headerx-api-key: <YOUR_MCP_TOKEN>

Step 1 — get a token: in the dashboard under “Connect an AI agent via MCP”, generate a token. Step 2 — set up the client (pick your agent):

Fastest way: one session, one command (Claude Code)

No setup, no config file. The command connects Claude Code to your MCP for this session only (insert your token):

claude --strict-mcp-config --mcp-config '{"mcpServers":{"1de-partner":{"type":"http","url":"https://deutschlandappwebpage.temmuz.uk/mcp","headers":{"x-api-key":"<DEIN_MCP_TOKEN>"}}}}'
For Claude Code only (inline via --mcp-config). A plain chat prompt cannot connect — the client always handles the MCP connection. For a permanent setup or other agents, see below.

Permanent / other agents

# Variante A — ein Befehl (Transport http + Custom-Header):
claude mcp add --transport http 1de-partner \
  https://deutschlandappwebpage.temmuz.uk/mcp \
  --header "x-api-key: <DEIN_MCP_TOKEN>"

# Variante B — projektweit per .mcp.json (ins Repo committen, Token via Env):
{
  "mcpServers": {
    "1de-partner": {
      "type": "http",
      "url": "https://deutschlandappwebpage.temmuz.uk/mcp",
      "headers": { "x-api-key": "${MCP_TOKEN}" }
    }
  }
}
# Prüfen:  claude mcp list   ·   in der Session:  /mcp

Get going right away — the first prompt

Give your agent this task first. It uses it to read everything in before it builds anything:

Du bist mein Entwickler für eine MiniApp im 1DE-/KOBIL-SuperApp-Ökosystem.

Lies dich ZUERST vollständig ein — rufe `get_docs` für ALLE Abschnitte auf und
verstehe: Was ist eine MiniApp, Schnellstart, miniApp.json, Design & Native Feel,
Authentifizierung (Silent SSO), Deeplinks, mPower (Chat, Signatur, Payment),
Discovery, Deploy — und wie man eine MiniApp anlegt (`create_miniapp`) und
deployt (`deploy_miniapp`).

WICHTIG zum Hosting: Soll auf 1DE gehostet werden, rufe `create_miniapp` OHNE `miniapp_url` auf —
es wird automatisch eine feste Subdomain vergeben und als URL/Redirect/Callback registriert.
Danach `deploy_miniapp` auf genau diese MiniApp → die URL stimmt immer (kein Mismatch). WebFlow bleibt aus.
Bei ÄNDERUNGEN/Updates: KEINE neue MiniApp anlegen! Dieselbe MiniApp per `deploy_miniapp` mit
derselben service_id erneut deployen (gleiche Subdomain, Container wird ersetzt). `create_miniapp` nur EINMAL.

Wenn du ALLES verstanden hast, frag NICHTS weiter ab, sondern melde dich bei mir:
„Ich bin bereit, deine MiniApp zu erstellen — was sollen wir bauen?"
und warte auf meine Idee. Erst danach legst du an, baust, und deployst.
The token binds all tools to your account — the agent only sees your MiniApps. Token compromised? Generate a new one in the dashboard; the old one is invalidated immediately.

Reference — Endpoints & Glossary

Glossary

TermMeaning
sIDService ID of your MiniApp = OIDC client_id = serviceUuid for mPower.
Silent SSOSign-in without typing; identity from the SuperApp.
Deep link<SHARE_BASE><sID>, opens a MiniApp as an overlay.
user_sessionYour own signed session cookie after the OIDC callback.

Endpoints

PurposeURL (placeholders from your config)
Authorize<ISSUER>/protocol/openid-connect/auth
Token<ISSUER>/protocol/openid-connect/token
JWKS<ISSUER>/protocol/openid-connect/certs
mPower Msg<MPOWER_BASE>/auth/realms/<TENANT>/mpower/v1/users/{userId}/message
Signature<MPOWER_BASE>/…/users/{userId}/signature
Payment<PAYMENT_BASE>/mpay-merchant/create/transaction
You'll find the real values for your MiniApp (incl. client_secret) in the dashboard — pre-filled and ready to copy.