Update Profile
Update the authenticated customer's profile fields
Update Profile
Update one or more fields on the authenticated customer's profile. Only the fields you include in the request body will be changed.
Endpoint
PATCH /profileAuthentication
Requires a valid JWT access token.
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...Request Body
For an existing profile, all fields are optional and only included fields are changed. If the authenticated account does not yet have a customer profile, this endpoint creates and links one; firstName is then required.
| Field | Type | Description |
|---|---|---|
firstName | string | Customer's first name |
lastName | string | Customer's last name |
phone | string | Phone number (e.g. +1234567890) |
profilePhoto | string | URL to a profile photo |
profileParameters | object | Editable customer parameters keyed by parameter ID or name |
emails | array | Full email list using { address, isPrimary, order } entries |
phones | array | Full phone list using { number, isPrimary, order } entries |
displayName is read-only. Tiquo derives it from firstName and lastName whenever either name changes.
When both phones and phone are supplied, the full phones array takes precedence. Sending an empty phone removes the current primary phone. Parameter values are validated against the organization's customer-editable parameter definitions.
During initial profile creation, the account email from the JWT becomes the primary email and the single phone field is used. Apply full emails or phones arrays in a later update after the profile exists.
The DOM Package also accepts a browser File or Blob for profilePhoto. When a file is provided, the SDK uploads the image through the profile photo upload endpoints before saving the customer profile.
createdAt and firstActiveAt are read-only system fields. They are returned on the customer object but are not accepted as profile updates. The Hosted and DOM packages also remove these fields from dynamically constructed update payloads.
New secondary email addresses cannot be introduced through PATCH /profile.
Verify ownership with the two endpoints below first.
Add a Verified Secondary Email
Send a verification code
POST /profile/email-verification/sendcurl -X POST "https://edge.tiquo.app/api/client/v1/profile/email-verification/send" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{"email":"second@example.com","portalSlug":"members"}'portalSlug is optional and selects the portal branding for the verification
email. The six-digit code expires after 10 minutes.
Verify and add the address
POST /profile/email-verification/verifycurl -X POST "https://edge.tiquo.app/api/client/v1/profile/email-verification/verify" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{"email":"second@example.com","otp":"123456"}'{
"success": true,
"data": {
"email": "second@example.com",
"emails": [
{ "address": "customer@example.com", "isPrimary": true, "order": 0 },
{ "address": "second@example.com", "isPrimary": false, "order": 1 }
]
}
}A profile can have up to five email addresses. The new address must not already be on this profile or another customer profile in the organization. Send and verify requests are rate limited, and repeated incorrect codes require a new code.
Example Request
curl -X PATCH "https://edge.tiquo.app/api/client/v1/profile" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"firstName": "John",
"lastName": "Smith",
"phone": "+1234567890"
}'Response
{
"success": true,
"data": {
"customer": {
"id": "cust_456",
"firstName": "John",
"lastName": "Smith",
"displayName": "John Smith",
"customerNumber": "CUST-000001",
"email": "customer@example.com",
"phone": "+1234567890",
"profilePhoto": null,
"createdAt": 1704067200000,
"firstActiveAt": 1706745600000,
"emails": [
{ "address": "customer@example.com", "isPrimary": true, "order": 0 }
],
"phones": [
{ "number": "+1234567890", "isPrimary": true, "order": 0 }
],
"parameters": [],
"parameterValues": {}
}
}
}For an existing profile, a successful response is 200 OK and includes the updated customer at both customer and data.customer.
When the endpoint creates a missing profile, it returns 201 Created. The new customer is always available at the top-level customer property. If profileParameters were also applied, the response additionally includes data.customer.
Profile Photo Uploads
For browser-based uploads, use the DOM Package uploadProfilePhoto() helper where possible.
If you are calling the Customer API directly, profile photo uploads use two steps:
- Request an upload URL.
- Upload the image to that URL, then finalise the profile photo with the returned
storageId.
Create Upload URL
POST /profile/photo-upload-urlThe request body can be an empty JSON object.
curl -X POST "https://edge.tiquo.app/api/client/v1/profile/photo-upload-url" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{}'The response includes a temporary uploadUrl.
{
"success": true,
"data": {
"uploadUrl": "https://..."
}
}Upload the image file to the returned URL using POST and the image content type. The upload response includes a storageId.
Finalise Profile Photo
POST /profile/photocurl -X POST "https://edge.tiquo.app/api/client/v1/profile/photo" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"storageId": "kg2..."
}'The upload must be a JPEG, PNG, GIF, or WebP image and be no larger than 5 MB.
The response includes the updated customer, the resolved profilePhoto URL, and the storageId.
Errors
| Status | Description |
|---|---|
400 | First name is missing during profile creation, or one or more field or parameter values are invalid |
401 | Invalid or expired access token |
500 | Internal server error |
Code Examples
JavaScript
const response = await fetch('https://edge.tiquo.app/api/client/v1/profile', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstName: 'John',
lastName: 'Smith',
}),
});
const { success, customer, data, error } = await response.json();
if (success) {
const updatedCustomer = data?.customer ?? customer;
console.log('Profile updated:', updatedCustomer.displayName);
}Swift
var request = URLRequest(url: URL(string: "https://edge.tiquo.app/api/client/v1/profile")!)
request.httpMethod = "PATCH"
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(["firstName": "John", "lastName": "Smith"])
let (data, _) = try await URLSession.shared.data(for: request)Kotlin
val body = """{"firstName": "John", "lastName": "Smith"}"""
.toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("https://edge.tiquo.app/api/client/v1/profile")
.patch(body)
.addHeader("Authorization", "Bearer $accessToken")
.build()
val response = client.newCall(request).execute()