Skip to content
Sections

Guest portal

Exchange a Guest Portal bootstrap token

POST/guest-portal/exchange

Atomically consumes the original fragment-delivered bootstrap capability. With exchangeId, the same token and nonce may recover the encrypted original continuation and optional recovery context only while the exact original subject, session, token hash and original expiry remain current. Recovery never renews or restores authority. Without exchangeId, exchange remains one-shot.

Authentication

A personal credential is supplied in body: guest-portal-bootstrap-token.

Connection guide

Parameters

No path, query or ordinary header parameters. See authentication and request body below.

Request body

Required

Original bootstrap token from the URL fragment and optional stable client-generated exchangeId UUID.

application/json

ExchangeGuestPortalTokenDto
Full definition
{
  "$ref": "#/components/schemas/ExchangeGuestPortalTokenDto"
}

Responses

200Original short-lived Guest Portal continuation, absolute expiry and optional non-reading recovery context; exact nonce recovery returns the same values.
GuestPortalBootstrapExchangeResultDto
Full definition
{
  "$ref": "#/components/schemas/GuestPortalBootstrapExchangeResultDto"
}
Example response · 200 · application/json
{
  "token": "synthetic-example-credentialxxxx",
  "expiresAt": "2026-12-31T18:00:00.000Z"
}
400The bootstrap token or optional exchangeId UUID is malformed.
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 400 · application/json
{
  "statusCode": 400,
  "error": "errors:http.badRequest",
  "code": "HTTP_BAD_REQUEST",
  "message": "errors:http.badRequest",
  "translationKey": "errors:http.badRequest"
}
401The original bootstrap, exchange nonce or current original session and subject are unavailable; recovery cannot revive expired, rotated or revoked authority.
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 401 · application/json
{
  "statusCode": 401,
  "error": "errors:http.unauthorized",
  "code": "HTTP_UNAUTHORIZED",
  "message": "errors:http.unauthorized",
  "translationKey": "errors:http.unauthorized"
}
503Required protected Guests encryption material is unavailable for a new recoverable exchange.
TranslatedErrorDto
Full definition
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Example response · 503 · application/json
{
  "statusCode": 503,
  "error": "errors:http.serviceUnavailable",
  "code": "HTTP_SERVICE_UNAVAILABLE",
  "message": "errors:http.serviceUnavailable",
  "translationKey": "errors:http.serviceUnavailable"
}

Schemas

ExchangeGuestPortalTokenDto

Original Guest Portal bootstrap token and optional caller nonce for bounded recovery of its first exchange.

tokenRequired

Bootstrap token recovered from the URL fragment.

string
Full definition
{
  "type": "string",
  "minLength": 48,
  "maxLength": 48,
  "pattern": "^gpb2_[A-Za-z0-9_-]{43}$",
  "example": "gpb2_synthetic-example-credentialxxxxxxxxxxxxxxx",
  "description": "Bootstrap token recovered from the URL fragment."
}
exchangeIdOptional

Client-generated exchange nonce. Retain and repeat it with the original bootstrap token after an uncertain response. Omission preserves one-shot exchange semantics.

string · uuid
Full definition
{
  "type": "string",
  "format": "uuid",
  "minLength": 36,
  "maxLength": 36,
  "example": "a0c17f9c-e25d-4b6f-8d22-f5e4f955cd8f",
  "description": "Client-generated exchange nonce. Retain and repeat it with the original bootstrap token after an uncertain response. Omission preserves one-shot exchange semantics."
}
Full definition
{
  "type": "object",
  "properties": {
    "token": {
      "type": "string",
      "minLength": 48,
      "maxLength": 48,
      "pattern": "^gpb2_[A-Za-z0-9_-]{43}$",
      "example": "gpb2_synthetic-example-credentialxxxxxxxxxxxxxxx",
      "description": "Bootstrap token recovered from the URL fragment."
    },
    "exchangeId": {
      "type": "string",
      "format": "uuid",
      "minLength": 36,
      "maxLength": 36,
      "example": "a0c17f9c-e25d-4b6f-8d22-f5e4f955cd8f",
      "description": "Client-generated exchange nonce. Retain and repeat it with the original bootstrap token after an uncertain response. Omission preserves one-shot exchange semantics."
    }
  },
  "required": [
    "token"
  ],
  "description": "Original Guest Portal bootstrap token and optional caller nonce for bounded recovery of its first exchange.",
  "example": {
    "token": "gpb2_synthetic-example-credentialxxxxxxxxxxxxxxx",
    "exchangeId": "a0c17f9c-e25d-4b6f-8d22-f5e4f955cd8f"
  }
}
GuestPortalBootstrapExchangeResultDto

Short-lived continuation returned after one-time bootstrap-token consumption.

tokenRequired

Rotated Guest Portal continuation token.

string
Full definition
{
  "type": "string",
  "minLength": 32,
  "description": "Rotated Guest Portal continuation token.",
  "example": "synthetic-example-credentialxxxx"
}
expiresAtRequired

Absolute expiration time for the continuation token.

string · date-time
Full definition
{
  "type": "string",
  "format": "date-time",
  "description": "Absolute expiration time for the continuation token.",
  "example": "2026-12-31T18:00:00.000Z"
}
reentryContextOptional

Optional sealed context and expiration for later Guest Portal re-entry using the current session and verified contact.

allOf
Full definition
{
  "allOf": [
    {
      "$ref": "#/components/schemas/GuestPortalReentryContextDto"
    }
  ],
  "description": "Optional sealed context and expiration for later Guest Portal re-entry using the current session and verified contact.",
  "example": {
    "hint": "gpr1_synthetic_recovery_context_example_not_a_runtime_credential_0000000000",
    "expiresAt": "2026-12-31T18:00:00.000Z"
  }
}
Full definition
{
  "type": "object",
  "description": "Short-lived continuation returned after one-time bootstrap-token consumption.",
  "required": [
    "token",
    "expiresAt"
  ],
  "properties": {
    "token": {
      "type": "string",
      "minLength": 32,
      "description": "Rotated Guest Portal continuation token.",
      "example": "synthetic-example-credentialxxxx"
    },
    "expiresAt": {
      "type": "string",
      "format": "date-time",
      "description": "Absolute expiration time for the continuation token.",
      "example": "2026-12-31T18:00:00.000Z"
    },
    "reentryContext": {
      "allOf": [
        {
          "$ref": "#/components/schemas/GuestPortalReentryContextDto"
        }
      ],
      "description": "Optional sealed context and expiration for later Guest Portal re-entry using the current session and verified contact.",
      "example": {
        "hint": "gpr1_synthetic_recovery_context_example_not_a_runtime_credential_0000000000",
        "expiresAt": "2026-12-31T18:00:00.000Z"
      }
    }
  },
  "example": {
    "token": "synthetic-example-credentialxxxx",
    "expiresAt": "2026-12-31T18:00:00.000Z"
  }
}
GuestPortalReentryContextDto

Non-reading recovery context for the original existing guest contact and portal scope. An unverified candidate still requires successful OTP confirmation. The context permits only the targeted reentry workflow, never portal, inbox or push access.

hintRequired

Opaque authenticated recovery hint. Store only as a recovery target; it is not a Guest Portal continuation or a push grant.

string
Full definition
{
  "type": "string",
  "description": "Opaque authenticated recovery hint. Store only as a recovery target; it is not a Guest Portal continuation or a push grant.",
  "minLength": 64,
  "maxLength": 2048,
  "pattern": "^gpr1_[A-Za-z0-9_-]+$",
  "example": "gpr1_synthetic_recovery_context_example_not_a_runtime_credential_0000000000",
  "readOnly": true
}
expiresAtRequired

Absolute recovery-target expiry. Current guest, original contact and portal scope remain authoritative before every code request and confirmation.

string · date-time
Full definition
{
  "type": "string",
  "description": "Absolute recovery-target expiry. Current guest, original contact and portal scope remain authoritative before every code request and confirmation.",
  "format": "date-time",
  "readOnly": true,
  "example": "2026-12-31T18:00:00.000Z"
}
Full definition
{
  "type": "object",
  "properties": {
    "hint": {
      "type": "string",
      "description": "Opaque authenticated recovery hint. Store only as a recovery target; it is not a Guest Portal continuation or a push grant.",
      "minLength": 64,
      "maxLength": 2048,
      "pattern": "^gpr1_[A-Za-z0-9_-]+$",
      "example": "gpr1_synthetic_recovery_context_example_not_a_runtime_credential_0000000000",
      "readOnly": true
    },
    "expiresAt": {
      "type": "string",
      "description": "Absolute recovery-target expiry. Current guest, original contact and portal scope remain authoritative before every code request and confirmation.",
      "format": "date-time",
      "readOnly": true,
      "example": "2026-12-31T18:00:00.000Z"
    }
  },
  "description": "Non-reading recovery context for the original existing guest contact and portal scope. An unverified candidate still requires successful OTP confirmation. The context permits only the targeted reentry workflow, never portal, inbox or push access.",
  "required": [
    "hint",
    "expiresAt"
  ],
  "example": {
    "hint": "gpr1_synthetic_recovery_context_example_not_a_runtime_credential_0000000000",
    "expiresAt": "2026-12-31T18:00:00.000Z"
  }
}
TranslatedErrorDto

Stable error envelope emitted by the global HTTP exception boundary. Domain-specific machine data, when present, is nested under details.

statusCodeRequired

HTTP status code repeated from the response.

integer
Full definition
{
  "type": "integer",
  "description": "HTTP status code repeated from the response.",
  "example": 400
}
errorRequired

Translation key for the HTTP category, such as errors:http.conflict. The specific cause is identified by code and translationKey.

string
Full definition
{
  "type": "string",
  "description": "Translation key for the HTTP category, such as errors:http.conflict. The specific cause is identified by code and translationKey.",
  "example": "errors.request.invalid"
}
codeRequired

Stable machine-readable domain code, or an HTTP_* fallback when no domain code is provided. Branch on this field and the HTTP status; localized wording never controls retries or business decisions.

string
Full definition
{
  "type": "string",
  "example": "HTTP_BAD_REQUEST",
  "description": "Stable machine-readable domain code, or an HTTP_* fallback when no domain code is provided. Branch on this field and the HTTP status; localized wording never controls retries or business decisions."
}
messageRequired

Translation key, identical to translationKey. The API does not return localized display text. Resolve the key and translationValues in the consuming application.

string
Full definition
{
  "type": "string",
  "example": "errors:http.badRequest",
  "description": "Translation key, identical to translationKey. The API does not return localized display text. Resolve the key and translationValues in the consuming application."
}
translationKeyRequired

Canonical translation key, identical to message. Status-specific errors:http.* keys cover unspecified failures. Public keys and EN/RU explanations are listed in Developers; unknown keys require a localized client fallback.

string
Full definition
{
  "type": "string",
  "example": "errors:http.badRequest",
  "description": "Canonical translation key, identical to message. Status-specific errors:http.* keys cover unspecified failures. Public keys and EN/RU explanations are listed in Developers; unknown keys require a localized client fallback."
}
translationValuesOptional

Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.

object
Full definition
{
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "type": "string",
        "example": "example"
      },
      {
        "type": "number",
        "example": 0
      },
      {
        "type": "boolean",
        "example": true
      }
    ],
    "example": "example"
  },
  "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
  "example": {
    "exampleKey": "example"
  }
}
validationErrorsOptional

Field validation failures with translation keys and stable validator codes. Submitted values and raw validator text are not included.

array
Full definition
{
  "description": "Field validation failures with translation keys and stable validator codes. Submitted values and raw validator text are not included.",
  "type": "array",
  "items": {
    "$ref": "#/components/schemas/ValidationErrorDto"
  },
  "example": [
    {
      "field": "email",
      "translationKey": "validation:isEmail",
      "code": "isEmail",
      "message": "validation:isEmail"
    }
  ]
}
detailsOptional

Optional domain-specific blocker or validation details

oneOf
Full definition
{
  "description": "Optional domain-specific blocker or validation details",
  "oneOf": [
    {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": [
        "example"
      ]
    },
    {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": {
        "exampleKey": "example"
      }
    }
  ],
  "example": [
    "example"
  ]
}
Full definition
{
  "type": "object",
  "properties": {
    "statusCode": {
      "type": "integer",
      "description": "HTTP status code repeated from the response.",
      "example": 400
    },
    "error": {
      "type": "string",
      "description": "Translation key for the HTTP category, such as errors:http.conflict. The specific cause is identified by code and translationKey.",
      "example": "errors.request.invalid"
    },
    "code": {
      "type": "string",
      "example": "HTTP_BAD_REQUEST",
      "description": "Stable machine-readable domain code, or an HTTP_* fallback when no domain code is provided. Branch on this field and the HTTP status; localized wording never controls retries or business decisions."
    },
    "message": {
      "type": "string",
      "example": "errors:http.badRequest",
      "description": "Translation key, identical to translationKey. The API does not return localized display text. Resolve the key and translationValues in the consuming application."
    },
    "translationKey": {
      "type": "string",
      "example": "errors:http.badRequest",
      "description": "Canonical translation key, identical to message. Status-specific errors:http.* keys cover unspecified failures. Public keys and EN/RU explanations are listed in Developers; unknown keys require a localized client fallback."
    },
    "translationValues": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "example": "example"
          },
          {
            "type": "number",
            "example": 0
          },
          {
            "type": "boolean",
            "example": true
          }
        ],
        "example": "example"
      },
      "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
      "example": {
        "exampleKey": "example"
      }
    },
    "validationErrors": {
      "description": "Field validation failures with translation keys and stable validator codes. Submitted values and raw validator text are not included.",
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/ValidationErrorDto"
      },
      "example": [
        {
          "field": "email",
          "translationKey": "validation:isEmail",
          "code": "isEmail",
          "message": "validation:isEmail"
        }
      ]
    },
    "details": {
      "description": "Optional domain-specific blocker or validation details",
      "oneOf": [
        {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/JsonValue"
          },
          "example": [
            "example"
          ]
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/components/schemas/JsonValue"
          },
          "example": {
            "exampleKey": "example"
          }
        }
      ],
      "example": [
        "example"
      ]
    }
  },
  "required": [
    "statusCode",
    "error",
    "code",
    "message",
    "translationKey"
  ],
  "description": "Stable error envelope emitted by the global HTTP exception boundary. Domain-specific machine data, when present, is nested under details.",
  "example": {
    "statusCode": 400,
    "error": "errors:http.badRequest",
    "code": "HTTP_BAD_REQUEST",
    "message": "errors:http.badRequest",
    "translationKey": "errors:http.badRequest"
  }
}
ValidationErrorDto

Field validation failure with a field path, stable validator code and a translation key. Human-readable text belongs to the consuming application.

fieldRequired

Public field path. Nested properties and array indices are separated by dots.

string
Full definition
{
  "type": "string",
  "example": "email",
  "description": "Public field path. Nested properties and array indices are separated by dots."
}
translationKeyRequired

Translation key for this validator, identical to message. Resolve it using a client dictionary; see the public Developers error catalog.

string
Full definition
{
  "type": "string",
  "example": "validation:isEmail",
  "description": "Translation key for this validator, identical to message. Resolve it using a client dictionary; see the public Developers error catalog."
}
codeRequired

Stable validator identifier for this field failure. Custom validators may define additional identifiers.

string
Full definition
{
  "type": "string",
  "example": "isEmail",
  "description": "Stable validator identifier for this field failure. Custom validators may define additional identifiers."
}
messageRequired

Translation key describing this field validation failure, identical to translationKey. Submitted values and validator prose are not included.

string
Full definition
{
  "type": "string",
  "example": "validation:isEmail",
  "description": "Translation key describing this field validation failure, identical to translationKey. Submitted values and validator prose are not included."
}
translationValuesOptional

Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.

object
Full definition
{
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "type": "string",
        "example": "example"
      },
      {
        "type": "number",
        "example": 0
      },
      {
        "type": "boolean",
        "example": true
      }
    ],
    "example": "example"
  },
  "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
  "example": {
    "exampleKey": "example"
  }
}
Full definition
{
  "type": "object",
  "properties": {
    "field": {
      "type": "string",
      "example": "email",
      "description": "Public field path. Nested properties and array indices are separated by dots."
    },
    "translationKey": {
      "type": "string",
      "example": "validation:isEmail",
      "description": "Translation key for this validator, identical to message. Resolve it using a client dictionary; see the public Developers error catalog."
    },
    "code": {
      "type": "string",
      "example": "isEmail",
      "description": "Stable validator identifier for this field failure. Custom validators may define additional identifiers."
    },
    "message": {
      "type": "string",
      "example": "validation:isEmail",
      "description": "Translation key describing this field validation failure, identical to translationKey. Submitted values and validator prose are not included."
    },
    "translationValues": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "example": "example"
          },
          {
            "type": "number",
            "example": 0
          },
          {
            "type": "boolean",
            "example": true
          }
        ],
        "example": "example"
      },
      "description": "Optional scalar values for placeholders in the translation. Treat values as data, escape them when rendering, and never use them as translation options.",
      "example": {
        "exampleKey": "example"
      }
    }
  },
  "required": [
    "field",
    "translationKey",
    "code",
    "message"
  ],
  "description": "Field validation failure with a field path, stable validator code and a translation key. Human-readable text belongs to the consuming application.",
  "example": {
    "field": "email",
    "translationKey": "validation:isEmail",
    "code": "isEmail",
    "message": "validation:isEmail"
  }
}
JsonValue

Recursively JSON-safe value used only where the owning contract intentionally allows free-form structured data.

Full definition
{
  "oneOf": [
    {
      "type": "string",
      "nullable": true,
      "example": "example"
    },
    {
      "type": "number",
      "example": 0
    },
    {
      "type": "boolean",
      "example": true
    },
    {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": [
        "example"
      ]
    },
    {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": {
        "exampleKey": "example"
      }
    }
  ],
  "description": "Recursively JSON-safe value used only where the owning contract intentionally allows free-form structured data.",
  "example": "example"
}

Hallify uses essential cookies and optional analytics.

Essential cookies keep sign-in, locale, and theme preferences working. Analytics is off until you choose to allow it.