Skip to main content
POST
/
integrations
/
users
Upsert a partner user
curl --request POST \
  --url http://localhost:4000/integrations/users \
  --header 'Content-Type: application/json' \
  --header 'x-partner-slug: <x-partner-slug>' \
  --header 'x-signature: <api-key>' \
  --data '
{
  "externalUserId": "<string>",
  "email": "jsmith@example.com",
  "displayName": "<string>",
  "phone": "<string>",
  "countryCode": "<string>",
  "locale": "<string>"
}
'
{
  "userId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}

Authorizations

x-signature
string
header
required

Stripe-style HMAC signature over ${timestamp}.${rawBody} using your partner secret. Format: t=<unix-seconds>,v1=<hex-hmac-sha256>. Also requires the x-partner-slug header to identify your account.

Headers

x-partner-slug
string
required

Your partner slug, assigned at onboarding (e.g. acme).

Body

application/json
externalUserId
string
required

Your stable identifier for this user (typically your DB primary key). Treated as opaque — we never decode it. Used as the JWT sub claim and in every outbound webhook payload to link your records to ours.

Required string length: 1 - 255
email
string<email> | null

User email. Pass null to clear; omit to leave unchanged.

Maximum string length: 320
displayName
string | null

Shown in our admin views and (absent a JWT override) in the webview.

Maximum string length: 200
phone
string | null

E.164 recommended but not enforced. Used only for support lookups.

Maximum string length: 40
countryCode
string | null

ISO 3166-1 alpha-2. Auto-uppercased server-side.

Required string length: 2
locale
string | null

BCP-47 locale tag (e.g. en-SG). Currently informational.

Maximum string length: 16

Response

User already existed; row updated in place.

User already existed; row updated in place.

userId
string<uuid>

Our internal user UUID. Stable across requests; safe to persist.

created
enum<boolean>
Available options:
false