OpenAPI referencePartner members

Declaratively set the member’s cards and face

PUT
/partner/members/{externalUserId}/credentials

Applies, in order: face (set / erase), the physical card set (enroll missing, revoke absent), then the auto-generated card rule — if the member now has a face and ZERO active physical cards, Keyspace mints ONE virtual card with a random unique number and returns it with generated: true so you can print/label a card. Card numbers default to Hikvision decimal-reversed. Supplying a face REQUIRES faceConsentAt. The member must be active (409 if offboarded — PUT the member first). Devices receive the credentials only through the access groups your app was provisioned with.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token from POST /auth/accessToken

In: header

Path Parameters

externalUserId*string

YOUR stable identifier for the user (opaque to Keyspace). Bound to exactly one Keyspace member per app on first PUT.

Lengthlength <= 128

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Declarative set of the member’s partner-managed credentials. Every field is independent: omit a field to leave that credential type untouched.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://example.com/partner/members/string/credentials" \  -H "Content-Type: application/json" \  -d '{}'
{  "code": "KS000",  "success": true,  "message": "string",  "data": {    "memberId": "string",    "cards": [      {        "cardId": "string",        "cardNo": "string",        "label": "string",        "type": "real",        "generated": true      }    ],    "face": {      "present": true    }  }}

Create or update one of YOUR users as a Keyspace member PUT

Idempotent on externalUserId. Resolves WHICH Keyspace member you mean before writing, in this order (first hit wins): (1) the member already linked to this externalUserId; (2) `email` → an existing Keyspace user (case-insensitive); (3) `phone` → an existing user after normalization (Thai numbers, `+66` default); (4) `employeeId` → a member of the project carrying that employee id; (5) nothing matched → a new member is created. A matched user that is not yet a member of your project is added as one. A key that resolves to a DIFFERENT member than the one already linked to this externalUserId — or to a member this app already manages under another externalUserId — is rejected 409 (`data.conflictKey` names the key); Keyspace never silently re-links. `unit` is a BINDING, never an identity: it places the member in the condo unit (first resident = reservation owner, later ones = participants) but never picks the person. First call links the member to your app and adds it to the access groups fixed at app provisioning (partnerAccessGroupIds) — devices only ever receive credentials through those groups (credential ≠ permission). Later calls update the profile. A previously offboarded member is re-activated by this call (same memberId, groups restored). Requires an app_credentials token (a delegated act_as token is rejected 403) and a single-project app.

Booking or visitor lifecycle event delivered to your registered listener URL Webhook

Booking or visitor lifecycle event delivered to your registered listener URL. Always HMAC-signed (X-Keyspace-Signature). If your endpoint requires its own auth, Keyspace also sends a credential per the webhook's authStrategy: 'signature-only' (none), 'bearer' (Authorization: Bearer <token>), 'custom-header' (one or more <name>: <value> headers), or 'jwt' (Authorization: Bearer <short-lived HS256 JWT signed with the shared secret; claims iss=keyspace, aud=projectId, jti=delivery id, exp>).