Developer overview
Use MimiKey third-party authorization v3 (SDK approval cards) to let your app read, create and update credentials with per-request user approval, without ever touching plaintext the user did not approve.
What you can build
MimiKey third-party authorization lets your app — an AI assistant, an automation tool, an internal business app — ask a user's MimiKey for credentials while it completes a task. The user never leaves your app's flow: they decide whether to share, which item, what to enter and what to change on approval cards rendered by MimiKey itself. Your app only ever receives a single result that the user approved, sealed to your current authorization.
| You can | You cannot |
|---|---|
| Ask the user to pick an item from the vaults they granted, and receive the full record | List or browse the user's items |
| Read an item by ID, subject to the user's approval policy | Read anything without user approval |
| Ask the user to create an item in MimiKey and receive the result | Draw your own credential-entry UI or handle passwords the user types |
| Submit a change that the user confirms on a diff card before it is written | Write without the user's confirmation |
| Revoke your own authorization at any time | Obtain a vault key or any lasting ability to decrypt |
Core concepts
| Concept | Description |
|---|---|
| Client | The app you register, identified by a client_id with the pmc_ prefix. There are two types: public (in-app SDK, no secret, PKCE for the token exchange) and confidential (your server holds a client_secret). iOS and macOS apps always use public. |
| Grant | One user's consent to one client. Each grant is bound to an approval key (Ed25519, signs every call) and a seal public key (X25519, receives sealed results), and is limited to the vaults the user selected. |
| Request | One operation you initiate: pick_item, get_item, create_item or update_item. Every request has a state machine and an expiry. |
| Approval card | The UI MimiKey renders for an authorization or a request: consent, pick, read approval, safety card (create) and update card. See Approval cards. |
| Executing device | The unlocked MimiKey device that renders the card. Approving on the card is the execution: it decrypts or writes locally, seals the result, uploads it and returns to your app. |
| Approval policy | Chosen by the user at consent: ask (approve every read) or trust (reads no longer ask, but still run when MimiKey is opened). Picking, creating and updating always require the user to act on a card. |
Why approval cards run inside MimiKey
If any UI that asks the user to decide ran inside your app's process, your process could click the button on the user's behalf, overlay a fake card, or read what the user types — whether or not you intended to, neither the user nor MimiKey could tell. So v3 requires that:
- Consent, pick, read, create and update UIs are always rendered by MimiKey's own process (the iOS app and the Mac app).
- Your app may only show non-decision notices such as "Opening MimiKey…", plus Retry and Cancel on its waiting screen.
- All you can customize is the branding allowlist: name, icon, brand color and homepage. Card structure, button semantics and risk notices are fixed by MimiKey.
This is also what lets users trust your app: they know every card they see is genuine.
End-to-end flow
Your app (SDK) MimiKey server MimiKey app (user's device)
│ │ │
1. ├─ generate seal key, approval key, PKCE, state
2. ├─ open mimikey://authorize ───────────────────────────────▶│ consent card
3. │ │◀──── POST /api/oauth/authorize ┤ user taps Allow
4. │◀────────────────── callback <redirect>?mk=authorize&code&state
5. ├─ POST /api/oauth/token (code + code_verifier) ▶│
│◀──────── access_token, refresh_token, grant_id ┤
6. ├─ POST /api/oauth/requests (signed) ──────────▶│
│◀────────────────────────────── request_id ─────┤
7. ├─ open mimikey://request?id=… ────────────────────────────▶│ approval card
8. │ │◀── device executes, seals, uploads ┤ user approves
9. │◀──────────── callback <redirect>?mk=request&request_id&state&status
10. ├─ GET /api/oauth/requests/{id} (signed; also polled every 2 s) ▶│
│◀────────────────────────── result_enc ─────────┤
11. └─ open the result locally with the seal private key
- The SDK generates a seal key pair and an approval key pair unique to this authorization (stored in the system keychain), plus a PKCE verifier and a random
state. - The SDK opens the
mimikey://authorizedeep link with theclient_id, redirect URL,state, PKCE challenge and both public keys. - MimiKey validates the client and redirect URL and, once the user has unlocked, shows the consent card. The user selects vaults, picks an approval policy and taps Allow.
- MimiKey opens your redirect URL with only
codeandstate. - The SDK exchanges the
codeand PKCE verifier for an access token (one hour) and a refresh token (30 days, sliding). - When it needs a credential, the SDK creates a request using the token plus an approval-key signature.
- The SDK opens the
mimikey://requestdeep link and MimiKey shows the matching approval card. - Once the user approves, the executing device decrypts or writes locally, seals the result to the seal public key and uploads it.
- MimiKey opens your redirect URL with only
request_id,stateandstatus. - The SDK fetches the request. If the callback is lost because the user switched back manually, polling every 2 seconds and an immediate check when your app returns to the foreground still pick up the result.
- The SDK opens the result locally with the seal private key and hands it to your code.
With the Swift SDK, all of this is wrapped in async methods such as authorize() and pickItem(). To implement the protocol yourself, see the API reference.
Execution modes
| Mode | Description | Status |
|---|---|---|
| Mode 1: device execution | You can only file requests. Decryption happens only on the user's unlocked device; results come back sealed and the server sees only ciphertext | The only available mode |
| Mode 2: server-side vault key | The user wraps an entire vault key for the integrator's server, which can then read that vault at any time | Retired for new grants: the consent card no longer offers it and mode: 2 returns 400 mode_retired; existing grants remain readable for compatibility |
Getting a client_id
Register in MimiKey for Mac (recommended)
- Sign in to MimiKey for Mac and click Developer access (开发者接入) in the sidebar.
- Click New app (新建应用) and fill in:
- Name (1–100 characters) and an optional description;
- Type: choose Public client (公开客户端) for an in-app SDK;
- Platforms (display only);
- Redirect URLs, one per line, for example
com.example.ai://mimikey/callback; - Optional brand color, homepage and icon URL.
- Click Register (登记). A public client shows only its
client_id. A confidential client also shows itsclient_secretonce only; store it in your server configuration right away.
The same page shows how many grants each app has and lets you disable (停用) an app. Disabling revokes all of its grants immediately and cannot be undone.
Register through the API
With an account session token you can also call POST /api/oauth/clients directly. See the API reference.
Redirect URL rules
| Client type | Allowed redirect URLs |
|---|---|
| public | Custom schemes (^[a-z][a-z0-9+.-]{1,63}://…, lowercase, not http, https or mimikey), plus https and loopback http |
| confidential | https://…; for local development, http://127.0.0.1… or http://localhost… |
- Each client has 1–10 redirect URLs of up to 500 characters each. Wildcards (
*) are not allowed. - Authorization and callbacks match the registered value exactly.
Note A hijacked custom scheme leaks nothing. Callback URLs carry only
code,request_id,stateandstatus; exchanging a code requires the PKCE verifier that exists only in your app, and fetching a result requires the approval and seal private keys that exist only in your app's keychain.
Branding allowlist
The brand block at the top of each approval card is the only part you can customize:
| Field | Rules | How it appears |
|---|---|---|
name | 1–100 characters | Your app's name, used in card titles (for example "{name} wants you to pick an item") |
brand.logo_url | Must be https, at most 500 characters | Rounded-square icon; falls back to the first letter of your name if it fails to load |
brand.color | #RRGGBB | Brand accent (stored in uppercase) |
brand.homepage | URL, at most 500 characters | Only the domain is shown |
platforms | Up to 10 entries of lowercase letters, digits, _ and - | Display only |
Other keys in brand are ignored. Card structure, button labels and semantics, expiry countdowns and risk notices are decided by MimiKey and cannot be customized.
Platform rules
- Never draw your own credential-entry UI. When a credential is missing, the only permitted action is a
create_itemrequest, so that the user types it on MimiKey's safety card. Your app must not collect, log or forward credentials the user enters, in any form. - Keep credentials out of hints.
reason,hint,prefillandfieldsare plaintext visible to the server and are shown to the user verbatim. - Respect the user's decisions. Honor revocations and denials. When you receive
refresh_token_reused,grant_revokedorclient_disabled, stop retrying automatically and ask the user to authorize again.
Integrators that break these rules can be disabled by the platform operator: all of their grants are revoked immediately, further calls return 401 client_disabled, and MimiKey refuses their deep links.
Next steps
- Swift SDK (iOS / macOS): integrate in five minutes.
- SDK download & demo app: download the SDK and run the full demo.
- Approval cards: what the user sees at every step.
- API reference and Errors: for implementing the protocol yourself.