---
title: "Complete a Secure Identity sign-in"
method: POST
path: "/hd/desks/{desk_id}/auth/identity/complete"
tags: ["hd"]
---

# Complete a Secure Identity sign-in

`POST /hd/desks/{desk_id}/auth/identity/complete`

## Request

- Base URL: `https://api.sparkvault.com/v1`
- URL: `https://api.sparkvault.com/v1/hd/desks/{desk_id}/auth/identity/complete`
- Auth: none required
- TypeScript: <https://skmtc.dev/sparkvault/apis/sparkvault-api/docs/hd/desks/:desk_id/auth/identity/complete/post.ts> (a function with typed inputs; its response is checked against the schema)

Trade the code the Identity origin returned to the portal's `/auth/callback` for the customer's tokens. The round trip must be this desk's, begun from the origin the request is sent from (its `Origin`) by the tab that sends its binding back, and is consumed once, so a callback link carrying someone else's code signs nobody in. The customer is the address the sign-in asserted, created at their first sign-in. The access token is the bearer of every signed-in request; the refresh token renews it. A sign-in that stops once its code is exchanged, refused or failed, hands out no tokens, and the session the code opened is revoked at the identity service.

## Path parameters

- `desk_id` string, required

## Headers

- `X-SV-Client` 'help-desk-portal', required

## Request body

- object
  - `code` string, required: The `code` the Identity origin returned with.
  - `state` string, required: The `state` it returned with.
  - `binding` string, required: The `binding` the start answered this tab.

## Response `200`

The customer's tokens and record.

- object
  - `data` HelpDeskIdentitySession, required
    - `token` string, required: The Secure Identity access token, the bearer of every signed-in request; the portal holds it in memory.
    - `expires_in` integer, required: Seconds until the access token expires.
    - `refresh_token` string, required: Renews the access token through the refresh route; each renewal answers the one to use next.
    - `return_to` string, required: The path the start's `return_to` named, its dot segments resolved.
    - `customer` HelpDeskCustomer, required: The signed-in customer, as the portal shows them.
      - `requester_id` string, required
      - `email` string, required: The address the customer proved.
      - `display_name` string, nullable, required: The name the desk shows the customer by; null until they give one.
      - `assurance` 'identity' | 'email_pin', required: How the customer last proved their address: Secure Identity, or an emailed code.
      - `email_updates` boolean: Whether the desk emails the customer updates on their requests. Present only where that choice is the desk's own switch, for a customer who last proved their address with an emailed code (`assurance` `email_pin`); a Secure Identity customer sets it in their notification preferences on auth.sv instead.
      - `needs_display_name` boolean, required: True until the customer gives a name: the portal asks for one first.
  - `meta` ResponseMeta: Envelope metadata present on every successful response.
    - `api_version` string
    - `request_id` string
    - `response_ms` integer
    - `timestamp` integer: Unix seconds.
    - `pools` object: Storage and bandwidth capacity snapshot for the account.
    - `billing` object
      - `past_due` boolean
    - `quota` object: This minute of the account request budget. Present on authenticated success responses that passed the throttle; absent otherwise.
      - `limit` integer
      - `used` integer
      - `remaining` integer
      - `resets_at` integer: Unix seconds.

## Other responses

- `400`: VALIDATION_ERROR — the body is no JSON object, or `code`, `state` or `binding` is not a non-empty string of at most 8192 characters; the round trip stands. SIGN_IN_INVALID — the one answer for every completion that is not a sign-in this tab began at this desk: the state is unknown, spent, expired or another desk's or origin's, the binding is another sign-in's (which spends the round trip), the code was refused, the person signed in with no email address, or the directory does not name them as the holder of the address their requests are under. CLIENT_HEADER_REQUIRED — see above.
- `409`: CONFLICT — the customer's record kept changing while the sign-in was recorded; sign in again.
- `429`: RATE_LIMIT_EXCEEDED — this client address has spent its reads at the desk for the minute, the sign-in would make the customer's record past the new customers the desk takes in an hour, or the identity service refused the code exchange for its rate. `Retry-After` carries the seconds until the budget reopens, and `details` carries `limit` and `resets_at`. The identity service's own refusal carries only what it names.
- `503`: HELP_DESK_UNAVAILABLE — the desk does not take customers right now, its customers do not sign in with Secure Identity now, or this customer is refused. INTERNAL_ERROR — the identity service did not answer, or answered no access token the desk accepts. BUDGET_UNAVAILABLE — a budget the request spends could not be counted, so the request was refused rather than let through uncounted; `Retry-After` carries the seconds to wait before trying again.

## Changes

- **2026-10-28** `a9a10e328ba5`: 16 info
  - the response property `error/details` became required for the status `400`
  - the response property `error/details` became required for the status `409`
  - the response property `error/details` became required for the status `429`
  - the response property `error/details` became required for the status `503`
  - …12 more
- **2026-10-28** `56d7c265a77a`: 4 breaking
  - the response property `error/details` became nullable for the status `400`
  - the response property `error/details` became nullable for the status `409`
  - the response property `error/details` became nullable for the status `429`
  - the response property `error/details` became nullable for the status `503`
- **2026-10-23** `ad4c62db5e08`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/sparkvault/apis/sparkvault-api/changes/hd/desks/:desk_id/auth/identity/complete/post.md)

---

[API](https://skmtc.dev/sparkvault/apis/sparkvault-api.md) - [All operations](https://skmtc.dev/sparkvault/apis/sparkvault-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sparkvault/apis/sparkvault-api/revisions/97cfadccd0c0?raw)
