NapX PMS Docs

Access Codes

Access-code and smart-lock API behavior in NapX PMS.

Access Codes

NapX PMS provisions guest access codes through the smart-lock adapter while keeping tenant isolation enforced by PostgreSQL Row-Level Security.

Endpoints

MethodPathDescription
POST/v1/smart-locks/connect-webviewCreates a tenant-scoped Seam Connect Webview for smart-lock onboarding
GET/v1/smart-locks/connect-webview/:idPolls the tenant-owned Seam Connect Webview until it reaches a terminal state
POST/v1/smart-locks/connect-accountStores the connected Seam account and triggers a device sync retry-safe flow
GET/v1/access-codesLists property-scoped access-code metadata and supports optional lock-device filtering
GET/v1/access-codes/:idReturns access-code metadata without PIN storage fields
GET/v1/access-codes/:id/codeReturns the stored PIN for one access code
GET/v1/reservations/:id/access-codesLists reservation access codes without exposing the stored PIN field
POST/v1/reservations/:id/access-codes/retryRe-runs provisioning for failed reservation access codes

Smart-Lock Onboarding

  • POST /v1/smart-locks/connect-webview creates the Seam Connect Webview and records its id against the authenticated tenant.
  • GET /v1/smart-locks/connect-webview/:id is tenant-scoped and still returns the final authorized state even if the webhook saves the connected account before the next client poll.
  • POST /v1/smart-locks/connect-account persists the connected account after verifying the authorized webview state, and a repeated call with the same account id retries device sync if the first sync attempt failed.

Response Shape

  • GET /v1/access-codes/:id returns access-code metadata such as syncStatus, startsAt, expiresAt, lockDeviceId, and seamAccessCodeId.
  • GET /v1/access-codes?propertyId=<uuid>&lockDeviceId=<uuid?> returns property-scoped access-code metadata rows and never returns the plain PIN field.
  • GET /v1/access-codes/:id/code returns { code: string | null }.
  • GET /v1/reservations/:id/access-codes returns an array of access-code metadata rows.
  • POST /v1/reservations/:id/access-codes/retry returns the reservation's active access-code rows after retry completes.

Security Model

  • Every request requires Authorization: Bearer <session-token>.
  • Tenant context is derived from validated auth claims, not from a client-supplied x-tenant-id header.
  • List and detail routes never expose the stored code field.
  • Plain PIN retrieval is limited to the dedicated /v1/access-codes/:id/code route.

Error Handling

  • 404 Not Found when the access code or reservation does not exist for the tenant.
  • 401 Unauthorized when the bearer token is missing or invalid.
  • 403 Forbidden when the authenticated session lacks valid tenant scope for the requested record.
  • GET /v1/reservations/:id/access-codes returns 200 [] when the reservation currently has no active access codes.

Retry Behavior

  • Retry only targets rows currently marked syncStatus = error.
  • Older duplicate error rows for the same lock device are soft-deleted during retry.
  • When reprovisioning is possible, the current error row is soft-deleted and a replacement row is created for the same reservation and lock device.
  • When the lock device can no longer be reprovisioned, the latest error row remains active so the failure is still visible and retryable.
  • Already-synced rows are not recreated.
  • Superseded or soft-deleted rows are not returned by the detail, list, or PIN lookup endpoints.

Operational Notes

  • Access codes are generated per connected lock device on the reservation's property or space.
  • Failed provisioning attempts are marked with syncStatus = error and can be retried later.
  • Generated guest PINs use the full 0000-9999 four-digit range.
  • Seam webhook events are signature-verified before sync-state updates when SEAM_WEBHOOK_SECRET is configured.
  • In non-production environments without SEAM_WEBHOOK_SECRET, the webhook endpoint accepts unsigned JSON payloads.
  • In production, the webhook endpoint returns 503 Service Unavailable until SEAM_WEBHOOK_SECRET is configured.

Example

GET /v1/access-codes/9f5aab77-2f7d-4d30-a4eb-7ae89b030d49/code
Authorization: Bearer <session-token>

See the API reference for the detailed endpoint contract.

On this page