<!-- markdown mirror of https://mintid.net/en/sdk/service-mode — generated at build time -->

> The same SDK wrapped in a thin first-party HTTP service you deploy yourself, behind a frozen, versioned OpenAPI contract.

index — 12 documents

1.  [overviewsdk/00](/en/sdk)
2.  [getting startedsdk/01](/en/sdk/getting-started)
3.  [python sdksdk/02](/en/sdk/python)
4.  [service modesdk/03](/en/sdk/service-mode)
    *   [the contract](#contract)
    *   [deploying](#deploying)
    *   [trust boundaries](#trust-boundaries)
5.  [typescript clientsdk/04](/en/sdk/typescript-client)
6.  [mcp serversdk/mcp](/en/sdk/mcp-server)
7.  [conformancesdk/05](/en/sdk/conformance)
8.  [reason codessdk/06](/en/sdk/reason-codes)
9.  [adr-0001 · kyc trust modeladr/0001](/en/sdk/adr-0001-kyc-trust-model)
10.  [adr-0002 · packagingadr/0002](/en/sdk/adr-0002-packaging)
11.  [adr-0003 · multi-languageadr/0003](/en/sdk/adr-0003-multilanguage)
12.  [bip-0001 · contract freezebip/0001](/en/sdk/bip-0001-verifier-service-contract)

SDK docs · sdk/03

# Service mode & the OpenAPI contract

The same SDK wrapped in a thin first-party HTTP service you deploy yourself, behind a frozen, versioned OpenAPI contract.

## The contract

Service mode is **embedded mode plus transport**: the same SDK wrapped in a thin first-party HTTP service that you deploy next to your backend. It adds no authority, exposes no extra options, and runs the identical nine-condition pipeline — there is no "lite" verification path. It exists so that non-Python backends (TypeScript today, PHP next) can integrate through transport-only clients.

`verifier-service.v1` — a versioned OpenAPI 3.1 document, frozen under the project's standards process. Three operations:

Operation

Method & path

Purpose

`createChallenge`

`POST /v1/challenges`

Issue one signed presentation challenge bound to the deployment's registered identity

`validatePresentation`

`POST /v1/presentations`

Run the nine conditions; returns the decision

`getBuildInfo`

`GET /v1/build-info`

The artifact's release pins (versions — never secrets)

Semver at the contract level: decision semantics or reason-vocabulary changes are **major**; additive surface is **minor** (current: 1.1.0, which added the conformance-suite pin to build-info).

**Deliberately absent from the wire** — these are invariants, not parameters: any lifetime setting (10 s is a constant), any skip flag for the conditions, and `max_height_lag` (local deployment policy, configured at service start — a compromised web tier must not be able to widen staleness acceptance).

### Decision vs transport error

*   Anything parseable into the challenge-response schema flows through the pipeline and returns **HTTP 200 with a decision** — accept or reject — plus exactly one decision record server-side.
*   **HTTP 400** exists only for bodies that cannot be parsed into the schema at all (no session identity exists, so no decision record is possible).
*   **HTTP 503** means the service refused to issue a challenge because proven chain state was unavailable — fail closed; retry, never work around.

## Deploying

Notes that matter:

*   **Identity is deployment configuration** (origin, verifier id, request key) — bound to your on-chain registrations, never accepted from HTTP callers.
*   **Challenge signing is your key custody.** The service takes a `RequestSigner` you provide (`--signer module:attribute`, e.g. an HSM wrapper). For devnet integration only, `--insecure-unsigned-challenges` exists and warns loudly.
*   The built-in runner is a single-threaded reference server for devnet and integration; front it with your own web tier for anything more.
*   The service holds no state: durability lives in the nonce store and the decision log you configured.

bashsdk/03 · verbatim

```
python -m verifier_core.service \
  --origin https://checkout.example \
  --verifier-id-hex <64 hex> \
  --request-key-id-hex <64 hex> \
  --state-rpc  http://your-rpc-node:26657 \
  --anchor-rpc http://your-own-node:26657 \
  --nonce-db   /var/lib/mintid/nonces.sqlite \
  --decision-log /var/log/mintid/decisions.jsonl \
  --signer your_pkg.signing:HsmRequestSigner
```

artifact

[verifier-service.v1.yaml](/openapi/verifier-service.v1.yaml)

format

OpenAPI 3.1 · contract 1.1.0

status

frozen — published verbatim

## Trust boundaries, restated

Your service instance is part of _your_ verifier. Deploy it inside your perimeter, point your transport clients at it, and never at anyone else's — outsourcing the service outsources the decision, which the protocol's paid-verification permission explicitly does not cover.

[previous← python sdk](/en/sdk/python)[nexttypescript client →](/en/sdk/typescript-client)

---
Source: https://mintid.net/en/sdk/service-mode · Service mode &amp; the OpenAPI contract — MintID verifier SDK docs
