Register customer account
Create a new customer account with email and password.
Returns user details and authentication tokens upon successful registration.
The email must be a real, deliverable address — disposable and example domains (e.g. example.com) are rejected with 400 invalid_email.
Password rule: a password must be 8 to 72 characters long (counted as characters, not bytes) and must not
be on the list of commonly used passwords, which is compared without regard to case. A password that breaks the rule
is refused with 400 weak_password and details.rule set to too_short, too_long or common. The rule is
checked before the email is looked up, so the refusal is the same whether or not the email already has an account.
Multi-Store Support:
- If the email is already registered at another store, a new customer record is created for this store (linked to the existing auth.users record)
- Response includes
is_multi_store_customer: truewhen linking to existing account - Customers can have accounts at multiple stores with the same email/password
⚠️ SECRET KEY REQUIRED
This endpoint requires a secret key (tybrite_sk_*). Publishable keys will return 403 Forbidden.
Why Secret Key? Authentication endpoints create and manage user sessions, which should only be performed from secure server-side environments.
Attempt limits: an account is never locked by attempts made on it. With a secret key, past
5 attempts for one email address from one store in 15 minutes, the call is slowed to one attempt
every 60 seconds; other calls for that address answer 429 rate_limited with a Retry-After header
giving the seconds until the next attempt is accepted. With a publishable key, attempts are
limited per calling address: 10 per address and email, and 30 per address, in 15 minutes. Across
every store and address, past 20 attempts for one email the call is slowed to one every 60 seconds.
Every attempt counts, successful or not, and an address with no account is treated identically.
curl --request POST \
--url https://api.tybritelabs.com/v1/auth/register \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "john.doe@tybritelabs.com",
"password": "SecurePassword123!",
"name": "John Doe",
"phone": "+12125550142",
"marketing_consent": true
}
'import requests
url = "https://api.tybritelabs.com/v1/auth/register"
payload = {
"email": "john.doe@tybritelabs.com",
"password": "SecurePassword123!",
"name": "John Doe",
"phone": "+12125550142",
"marketing_consent": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
email: 'john.doe@tybritelabs.com',
password: 'SecurePassword123!',
name: 'John Doe',
phone: '+12125550142',
marketing_consent: true
})
};
fetch('https://api.tybritelabs.com/v1/auth/register', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.tybritelabs.com/v1/auth/register",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'email' => 'john.doe@tybritelabs.com',
'password' => 'SecurePassword123!',
'name' => 'John Doe',
'phone' => '+12125550142',
'marketing_consent' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.tybritelabs.com/v1/auth/register"
payload := strings.NewReader("{\n \"email\": \"john.doe@tybritelabs.com\",\n \"password\": \"SecurePassword123!\",\n \"name\": \"John Doe\",\n \"phone\": \"+12125550142\",\n \"marketing_consent\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.tybritelabs.com/v1/auth/register")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"john.doe@tybritelabs.com\",\n \"password\": \"SecurePassword123!\",\n \"name\": \"John Doe\",\n \"phone\": \"+12125550142\",\n \"marketing_consent\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/auth/register")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"email\": \"john.doe@tybritelabs.com\",\n \"password\": \"SecurePassword123!\",\n \"name\": \"John Doe\",\n \"phone\": \"+12125550142\",\n \"marketing_consent\": true\n}"
response = http.request(request)
puts response.read_body{
"message": "Registration successful",
"user": {
"id": "633e7cb6-00c6-4aac-b03c-c3d70d64e25c",
"email": "john.doe@tybritelabs.com",
"email_confirmed": true
},
"customer": {
"id": "de11e44b-78e5-4940-ad54-cac237d5d30d",
"name": "John Doe",
"email": "john.doe@tybritelabs.com",
"phone": "+12125550142",
"created_at": "2026-06-20T13:47:38.831799+00:00"
},
"session": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzNlN2NiNiJ9.<redacted-signature>",
"refresh_token": "67ksfnj5dyj6",
"expires_in": 3600,
"expires_at": 1781966858
},
"is_multi_store_customer": false
}Authorizations
API Key Authentication
Use your API key in the Authorization header:
Authorization: Bearer tybrite_sk_live_YOUR_KEY
Key Types:
Secret Keys (Server-Side Only):
- Format:
tybrite_sk_live_*(production) ortybrite_sk_test_*(sandbox) - Full read/write access to all endpoints
- ⚠️ NEVER expose in client-side code or public repositories
- Required for: every write a shopper does not make for themselves, authentication, payment verification, AI recommendations
Publishable Keys (Client-Safe):
- Format:
tybrite_pk_live_*(production) ortybrite_pk_test_*(sandbox) - Catalogue reads, plus the actions a shopper takes for themselves
- ✅ Safe for client-side JavaScript, mobile apps, and public code
- Allowed for: browsing products, search, CMS content, pricing queries, cart and wishlist, reviews, storefront events, and the Agent API's quotes, cart drafts and checkout intents
Endpoint-Specific Requirements:
- Authentication endpoints (
/v1/auth/*): Secret key required - Payment verification (
POST /v1/payments/verify): Secret key required - AI Recommendations (
POST /v1/recommendations): Secret key required - Semantic Search (
POST /v1/search): Both key types allowed (read-only operation) - Shopper actions (cart, wishlist, reviews, storefront events, Agent API quotes, cart drafts and checkout intents): Both key types allowed
- All other write operations: Secret key required
- All read operations: Both key types allowed
Using a publishable key for restricted operations returns 403 Forbidden.
Body
Customer email address
"john.doe@tybritelabs.com"
Password, 8 to 72 characters, not on the list of commonly used passwords.
8 - 72"SecurePassword123!"
Customer full name
"John Doe"
Phone number with country code
"+12125550142"
Whether the customer opted in to marketing communications at sign-up. Defaults to false (opt-in). Pass the state of your sign-up form's marketing opt-in checkbox.
true
Response
Registration successful
Success message
"Registration successful"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Indicates if this customer already had an account at another store. When true, the customer's auth.users record already existed, and a new customers record was created for this store. When false or omitted, this is the customer's first store registration.
false
curl --request POST \
--url https://api.tybritelabs.com/v1/auth/register \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "john.doe@tybritelabs.com",
"password": "SecurePassword123!",
"name": "John Doe",
"phone": "+12125550142",
"marketing_consent": true
}
'import requests
url = "https://api.tybritelabs.com/v1/auth/register"
payload = {
"email": "john.doe@tybritelabs.com",
"password": "SecurePassword123!",
"name": "John Doe",
"phone": "+12125550142",
"marketing_consent": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
email: 'john.doe@tybritelabs.com',
password: 'SecurePassword123!',
name: 'John Doe',
phone: '+12125550142',
marketing_consent: true
})
};
fetch('https://api.tybritelabs.com/v1/auth/register', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.tybritelabs.com/v1/auth/register",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'email' => 'john.doe@tybritelabs.com',
'password' => 'SecurePassword123!',
'name' => 'John Doe',
'phone' => '+12125550142',
'marketing_consent' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.tybritelabs.com/v1/auth/register"
payload := strings.NewReader("{\n \"email\": \"john.doe@tybritelabs.com\",\n \"password\": \"SecurePassword123!\",\n \"name\": \"John Doe\",\n \"phone\": \"+12125550142\",\n \"marketing_consent\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.tybritelabs.com/v1/auth/register")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"john.doe@tybritelabs.com\",\n \"password\": \"SecurePassword123!\",\n \"name\": \"John Doe\",\n \"phone\": \"+12125550142\",\n \"marketing_consent\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tybritelabs.com/v1/auth/register")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"email\": \"john.doe@tybritelabs.com\",\n \"password\": \"SecurePassword123!\",\n \"name\": \"John Doe\",\n \"phone\": \"+12125550142\",\n \"marketing_consent\": true\n}"
response = http.request(request)
puts response.read_body{
"message": "Registration successful",
"user": {
"id": "633e7cb6-00c6-4aac-b03c-c3d70d64e25c",
"email": "john.doe@tybritelabs.com",
"email_confirmed": true
},
"customer": {
"id": "de11e44b-78e5-4940-ad54-cac237d5d30d",
"name": "John Doe",
"email": "john.doe@tybritelabs.com",
"phone": "+12125550142",
"created_at": "2026-06-20T13:47:38.831799+00:00"
},
"session": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzNlN2NiNiJ9.<redacted-signature>",
"refresh_token": "67ksfnj5dyj6",
"expires_in": 3600,
"expires_at": 1781966858
},
"is_multi_store_customer": false
}
