Documentation / Developers

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 canYou cannot
Ask the user to pick an item from the vaults they granted, and receive the full recordList or browse the user's items
Read an item by ID, subject to the user's approval policyRead anything without user approval
Ask the user to create an item in MimiKey and receive the resultDraw 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 writtenWrite without the user's confirmation
Revoke your own authorization at any timeObtain a vault key or any lasting ability to decrypt

Core concepts

ConceptDescription
ClientThe 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.
GrantOne 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.
RequestOne operation you initiate: pick_item, get_item, create_item or update_item. Every request has a state machine and an expiry.
Approval cardThe UI MimiKey renders for an authorization or a request: consent, pick, read approval, safety card (create) and update card. See Approval cards.
Executing deviceThe 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 policyChosen 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
  1. 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.
  2. The SDK opens the mimikey://authorize deep link with the client_id, redirect URL, state, PKCE challenge and both public keys.
  3. 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.
  4. MimiKey opens your redirect URL with only code and state.
  5. The SDK exchanges the code and PKCE verifier for an access token (one hour) and a refresh token (30 days, sliding).
  6. When it needs a credential, the SDK creates a request using the token plus an approval-key signature.
  7. The SDK opens the mimikey://request deep link and MimiKey shows the matching approval card.
  8. Once the user approves, the executing device decrypts or writes locally, seals the result to the seal public key and uploads it.
  9. MimiKey opens your redirect URL with only request_id, state and status.
  10. 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.
  11. 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

ModeDescriptionStatus
Mode 1: device executionYou can only file requests. Decryption happens only on the user's unlocked device; results come back sealed and the server sees only ciphertextThe only available mode
Mode 2: server-side vault keyThe user wraps an entire vault key for the integrator's server, which can then read that vault at any timeRetired 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

  1. Sign in to MimiKey for Mac and click Developer access (开发者接入) in the sidebar.
  2. 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.
  3. Click Register (登记). A public client shows only its client_id. A confidential client also shows its client_secret once 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 typeAllowed redirect URLs
publicCustom schemes (^[a-z][a-z0-9+.-]{1,63}://…, lowercase, not http, https or mimikey), plus https and loopback http
confidentialhttps://…; 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, state and status; 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:

FieldRulesHow it appears
name1–100 charactersYour app's name, used in card titles (for example "{name} wants you to pick an item")
brand.logo_urlMust be https, at most 500 charactersRounded-square icon; falls back to the first letter of your name if it fails to load
brand.color#RRGGBBBrand accent (stored in uppercase)
brand.homepageURL, at most 500 charactersOnly the domain is shown
platformsUp 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_item request, 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, prefill and fields are 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_revoked or client_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

Last updated: 2026-10-23