Skip to main content

    Developer docs

    Build scoped onboarding integrations

    Use firm-owned API integrations to create cases, add parties, and send onboarding invites from another system with auditable, least-privilege access.

    AI-ready reference

    Stable URLs, schemas, examples, and guardrails.

    Versionv1 REST endpoints
    AuthClient credentials -> scoped system JWT
    AuditAll actions attributed to the integration
    Machine filesllms.txt and OpenAPI YAML

    Quickstart

    From firm setup to first case

    The integration flow is intentionally small: create credentials, request a scoped token, then call only the endpoints enabled by the firm.

    1

    Create the integration

    A firm admin creates an API integration in Firm -> Apps & API access and chooses the least scopes required.

    2

    Store credentials

    Use the returned appId as clientId and store the one-time clientSecret in a backend secret manager.

    3

    Issue a system token

    Exchange client credentials for a short-lived MicroApp system token.

    4

    Call scoped endpoints

    Create cases, add parties, and send invites with Authorization: Bearer <accessToken>.

    Browser proxy

    /api/v1

    Local API

    http://localhost:8081/v1

    Production

    Use relative /api/v1 from browser contexts

    Authentication

    Client credentials issue short-lived tokens

    Secrets never belong in browser code. This is a POST-only server-side call: exchange credentials from your backend for a MicroApp system token, then send the bearer token with each scoped API call.

    Create system tokenbash
    curl -X POST "$VERIFY_CLIENT_BASE_URL/v1/microapps/system-tokens" \
      -H "Content-Type: application/json" \
      -d '{
        "clientId": "00000000-0000-0000-0000-000000000000",
        "clientSecret": "$VERIFY_CLIENT_CLIENT_SECRET",
        "scopes": ["cases.create"],
        "expiresInSeconds": 3600
      }'
    Create case with tokenbash
    curl -X POST "$VERIFY_CLIENT_BASE_URL/v1/cases" \
      -H "Authorization: Bearer $VERIFY_CLIENT_ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "matterRef": "MAT-2026-001",
        "matterType": "Purchase",
        "parties": [
          {
            "name": "Alex Client",
            "email": "alex@example.com",
            "role": "Buyer"
          }
        ]
      }'

    One-time secret

    The clientSecret is shown only when created or rotated.

    Scoped token

    Requested scopes are intersected with firm-enabled scopes.

    IP restrictions

    allowedIpRanges are enforced at token issuance and API use.

    Endpoint reference

    Supported automation endpoints

    These are the endpoints currently documented for server-to-server onboarding. Do not invent endpoints; inspect implementation before using anything outside this list.

    POST/v1/microapps/system-tokens

    Create system token

    Exchanges an API integration clientId and clientSecret for a scoped JWT.

    client credentials
    Request bodyjson
    {
      "clientId": "00000000-0000-0000-0000-000000000000",
      "clientSecret": "stored-secret",
      "scopes": ["cases.create"],
      "expiresInSeconds": 3600
    }
    Response bodyjson
    {
      "ok": true,
      "accessToken": "<jwt>",
      "principal": {
        "principalType": "microApp",
        "tokenKind": "system",
        "appId": "00000000-0000-0000-0000-000000000000",
        "orgId": "org_123",
        "identifier": "case-management-system",
        "scopes": ["cases.create"]
      },
      "expiresAt": 1770000000
    }
    POST/v1/cases

    Create case

    Creates an onboarding matter and can include initial parties in the same request.

    cases.create
    Request bodyjson
    {
      "matterRef": "MAT-2026-001",
      "matterType": "Purchase",
      "propertyAddress": {
        "line1": "1 High Street",
        "city": "London",
        "postcode": "SW1A 1AA"
      },
      "requireSof": true,
      "parties": [
        {
          "name": "Alex Client",
          "email": "alex@example.com",
          "mobile": "+447700900123",
          "role": "Buyer",
          "partyType": "individual",
          "isPrimaryContact": true
        }
      ]
    }
    Response bodyjson
    {
      "caseId": "case_opaque_id",
      "status": "NotStarted",
      "parties": [
        {
          "partyId": "party_opaque_id",
          "name": "Alex Client",
          "clientAccessStatus": "not_sent"
        }
      ]
    }
    GET/v1/microapps/api/cases/ids

    List case IDs

    Returns paginated opaque case IDs for remote ledger sync and duplicate-check connectivity.

    cases.ids.list
    Requesthttp
    GET /v1/microapps/api/cases/ids?limit=200&cursor=<nextCursor>
    Authorization: Bearer <system-token>
    Response bodyjson
    {
      "ok": true,
      "items": ["case_opaque_id"],
      "nextCursor": null
    }
    POST/v1/cases/{caseId}/parties

    Add party

    Adds an individual or company party to an existing case.

    parties.manage
    Request bodyjson
    {
      "name": "Jordan Client",
      "email": "jordan@example.com",
      "mobile": "+447700900456",
      "role": "Seller",
      "partyType": "individual"
    }
    Response bodyjson
    {
      "partyId": "party_opaque_id",
      "name": "Jordan Client",
      "email": "jordan@example.com",
      "role": "Seller",
      "clientAccessStatus": "not_sent"
    }
    POST/v1/cases/{caseId}/invites

    Send invite

    Sends a client onboarding invite by email or SMS according to party details.

    invites.send
    Request bodyjson
    {
      "partyId": "party_opaque_id",
      "sendSms": false
    }
    Response bodyjson
    {
      "ok": true,
      "inviteId": "invite_opaque_id",
      "channel": "email"
    }

    Duplicate safeguards

    Keep live creation blocked when remote state is unknown

    Use a stable source-system matterRef for every case. Verify Client rejects duplicate matter references within the firm, and integrations should keep a local ledger plus a remote sync check where required.

    Recommended flow

    1. 1Check your local sync ledger for the source matter/reference.
    2. 2Refresh the remote case-ID ledger when your workflow requires a remote duplicate check.
    3. 3Create the case only when local and remote checks are conclusive.
    4. 4Treat a duplicate matterRef response from POST /v1/cases as an existing case, not a retryable failure.

    Remote check outcomes

    200
    Use the returned page and continue until nextCursor is null when a complete sync is required.
    400
    Fix the request, usually an invalid cursor. Do not retry unchanged.
    401
    Refresh the system token or rotate/check credentials. Do not report this as duplicate uncertainty.
    403
    A firm admin must enable the scope, integration status, or source IP/origin configuration.
    5xx
    Remote state is unknown. Block live creation unless an operator explicitly accepts local-ledger-only dedupe.

    Scopes and schemas

    Least-privilege permissions

    Use the smallest scope set possible. Treat all identifiers as opaque strings and persist only the IDs needed to continue a workflow.

    ScopePurposeEndpoint
    cases.createCreate onboarding casesPOST /v1/cases
    parties.manageAdd parties to a casePOST /v1/cases/{caseId}/parties
    invites.sendSend onboarding invitesPOST /v1/cases/{caseId}/invites
    cases.ids.listList case IDsGET /v1/microapps/api/cases/ids
    users.listList firm usersGET /v1/microapps/api/users

    Errors and audit

    Plan for explicit failure states

    Integrations should branch on HTTP status first. Error body fields are useful but should be treated as optional.

    Status codes

    400
    Missing or invalid payload field
    401
    Missing, expired, malformed, or invalid credentials. Refresh or rotate credentials.
    403
    Valid credentials but missing scope, active integration status, or source IP allowance.
    404
    Route not found
    500
    Server error. Retry safely; block live creation if remote duplicate state is required and unknown.

    Audit attribution

    Case, party, and invite actions performed by system tokens are written as MicroApp audit actors with the integration appId and identifier.

    Audit actor shapejson
    {
      "actorType": "microApp",
      "actorId": "<appId>",
      "meta": {
        "actorTokenKind": "system",
        "actorIdentifier": "<identifier>"
      }
    }

    AI files

    Machine-readable entrypoints

    AI coding tools should start with llms.txt, then use the OpenAPI slice for schemas. Humans can use the same files to verify what automation is supported.

    AI builder rules

    • Do not expose clientSecret in frontend code, logs, source control, or prompts.
    • Request only the scopes needed for the current workflow.
    • Cache tokens only until expiry and refresh server-side.
    • Do not retry invalid credentials indefinitely.
    • Validate returned caseId and partyId before continuing.
    • Use fixed egress IPs when firms configure allowedIpRanges.

    Need production access?

    Firm admins manage integrations from Apps & API access.

    Talk to us