# Customers

Customer data and management

## GET /rest\_api/v2/customers

> Get customers with pagination

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers":{"get":{"tags":["Customers"],"summary":"Get customers with pagination","parameters":[{"$ref":"#/components/parameters/AppKeyHeader"},{"$ref":"#/components/parameters/SecretKeyHeader"},{"name":"before","in":"query","schema":{"type":"string"},"description":"Cursor for pagination (before) - Firestore document ID of customer to paginate before"},{"name":"after","in":"query","schema":{"type":"string"},"description":"Cursor for pagination (after) - Firestore document ID of customer to paginate after"},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"minimum":1,"maximum":1000},"description":"Number of customers per page"},{"name":"email","in":"query","schema":{"type":"string"},"description":"Search by customer email address"},{"name":"type","in":"query","schema":{"type":"string","enum":["member","guest","left"]},"description":"Filter by customer type"},{"name":"tierId","in":"query","schema":{"type":"string"},"description":"Filter by customer tier ID"},{"name":"updated_at_min","in":"query","schema":{"type":"string","format":"date-time"},"description":"Filter customers updated after this date"},{"name":"updated_at_max","in":"query","schema":{"type":"string","format":"date-time"},"description":"Filter customers updated before this date"},{"name":"created_at_max","in":"query","schema":{"type":"string","format":"date-time"},"description":"Filter customers created before this date"},{"name":"order","in":"query","schema":{"type":"string","enum":["createdAt_desc","createdAt_asc","updatedAt_desc","updatedAt_asc","point_desc","point_asc"],"default":"createdAt_desc"},"description":"Sort order for results"},{"name":"hasCount","in":"query","schema":{"type":"boolean","default":false},"description":"Include total count in response (may increase response time)"}],"responses":{"200":{"description":"Paginated list of customers","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}}}}]}}}}}}}},"components":{"parameters":{"AppKeyHeader":{"name":"X-Joy-Loyalty-App-Key","in":"header","required":true,"schema":{"type":"string"},"description":"App ID of your shop which retrieved from the Settings page"},"SecretKeyHeader":{"name":"X-Joy-Loyalty-Secret-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Secret Key of your shop which retrieved from the Settings page"}},"schemas":{"PaginatedResponse":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object"},"description":"Array of items for current page"},"meta":{"type":"object","properties":{"pagination":{"type":"object","required":["hasNext","hasPre"],"properties":{"hasNext":{"type":"boolean","description":"True if more results exist after current page"},"hasPre":{"type":"boolean","description":"True if results exist before current page"},"total":{"type":"integer","description":"Total count of all matching results (when available)"},"totalPage":{"type":"integer","description":"Total number of pages calculated as ceil(total/limit) (when available)"}}}},"description":"Pagination metadata container"}}}]},"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"Customer":{"type":"object","properties":{"id":{"type":"string","description":"Internal customer ID"},"shopifyCustomerId":{"type":"integer","description":"Shopify customer ID"},"email":{"type":"string","format":"email","description":"Customer email address"},"name":{"type":"string","description":"Customer full name"},"firstName":{"type":"string","description":"Customer first name"},"lastName":{"type":"string","description":"Customer last name"},"type":{"type":"string","enum":["member","guest","left"],"description":"Customer type"},"point":{"type":"integer","description":"Current available points"},"tierPoint":{"type":"integer","description":"Points used for tier calculation"},"pendingPoint":{"type":"integer","description":"Points pending approval"},"totalSpent":{"type":"number","description":"Total amount spent"},"totalEarnedPoints":{"type":"integer","description":"Lifetime earned points"},"hasPoint":{"type":"boolean","description":"Whether customer has available points"},"hasJoinedProgram":{"type":"boolean","description":"Whether customer joined loyalty program"},"orderCount":{"type":"integer","description":"Number of orders placed"},"state":{"type":"string","enum":["enabled","disabled"],"description":"Account state"},"latestActivity":{"type":"string","format":"date-time","description":"Last activity timestamp"},"notifications":{"type":"object","description":"Customer notification preferences"},"acceptsMarketing":{"type":"boolean","description":"Marketing consent"},"birthday":{"type":"string","description":"Birthday in MM/DD format"},"dateOfBirth":{"type":"string","format":"date","description":"Date of birth in YYYY-MM-DD format"},"tierId":{"type":"string","description":"Current tier ID"},"tierName":{"type":"string","description":"Current tier name"},"tierUpdatedAt":{"type":"string","format":"date-time","description":"Last tier update timestamp"},"phone":{"type":"string","nullable":true,"description":"Phone number"},"pointsRemain":{"type":"integer","description":"Points needed for next tier"},"birthMonth":{"type":"string","description":"Birth month in MM format"},"isCustomerB2B":{"type":"boolean","description":"Whether customer is B2B"},"earnSignUp":{"type":"boolean","description":"Whether customer earned signup points"},"referralCode":{"type":"string","description":"Customer's referral code"},"hasTier":{"type":"boolean","description":"Whether customer has a tier assigned"},"totalSpentCurrencyCode":{"type":"string","description":"Currency code for spending"},"createdAt":{"type":"string","format":"date-time","description":"Account creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"}}}}}}
```

## GET /rest\_api/v2/customers/{customerId}

> Get customer by ID

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/{customerId}":{"get":{"tags":["Customers"],"summary":"Get customer by ID","parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"},"description":"Internal customer ID"}],"responses":{"200":{"description":"Customer details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Customer"}}}]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"Customer":{"type":"object","properties":{"id":{"type":"string","description":"Internal customer ID"},"shopifyCustomerId":{"type":"integer","description":"Shopify customer ID"},"email":{"type":"string","format":"email","description":"Customer email address"},"name":{"type":"string","description":"Customer full name"},"firstName":{"type":"string","description":"Customer first name"},"lastName":{"type":"string","description":"Customer last name"},"type":{"type":"string","enum":["member","guest","left"],"description":"Customer type"},"point":{"type":"integer","description":"Current available points"},"tierPoint":{"type":"integer","description":"Points used for tier calculation"},"pendingPoint":{"type":"integer","description":"Points pending approval"},"totalSpent":{"type":"number","description":"Total amount spent"},"totalEarnedPoints":{"type":"integer","description":"Lifetime earned points"},"hasPoint":{"type":"boolean","description":"Whether customer has available points"},"hasJoinedProgram":{"type":"boolean","description":"Whether customer joined loyalty program"},"orderCount":{"type":"integer","description":"Number of orders placed"},"state":{"type":"string","enum":["enabled","disabled"],"description":"Account state"},"latestActivity":{"type":"string","format":"date-time","description":"Last activity timestamp"},"notifications":{"type":"object","description":"Customer notification preferences"},"acceptsMarketing":{"type":"boolean","description":"Marketing consent"},"birthday":{"type":"string","description":"Birthday in MM/DD format"},"dateOfBirth":{"type":"string","format":"date","description":"Date of birth in YYYY-MM-DD format"},"tierId":{"type":"string","description":"Current tier ID"},"tierName":{"type":"string","description":"Current tier name"},"tierUpdatedAt":{"type":"string","format":"date-time","description":"Last tier update timestamp"},"phone":{"type":"string","nullable":true,"description":"Phone number"},"pointsRemain":{"type":"integer","description":"Points needed for next tier"},"birthMonth":{"type":"string","description":"Birth month in MM format"},"isCustomerB2B":{"type":"boolean","description":"Whether customer is B2B"},"earnSignUp":{"type":"boolean","description":"Whether customer earned signup points"},"referralCode":{"type":"string","description":"Customer's referral code"},"hasTier":{"type":"boolean","description":"Whether customer has a tier assigned"},"totalSpentCurrencyCode":{"type":"string","description":"Currency code for spending"},"createdAt":{"type":"string","format":"date-time","description":"Account creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string"},"statusCode":{"type":"integer"},"details":{"type":"object"}}},"timestamp":{"type":"string","format":"date-time"}}}}}}
```

## Update customer data

> Update customer information (supports birthday fields)

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/{customerId}":{"put":{"tags":["Customers"],"summary":"Update customer data","description":"Update customer information (supports birthday fields)","parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"},"description":"Internal customer ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dateOfBirth":{"type":"string","format":"date","description":"Date of birth in ISO 8601 format (YYYY-MM-DD)"},"birthday":{"type":"string","description":"Birthday in MM/DD format"}}}}}},"responses":{"200":{"description":"Customer updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shopifyCustomerId":{"type":"string"}}}}}]}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string"},"statusCode":{"type":"integer"},"details":{"type":"object"}}},"timestamp":{"type":"string","format":"date-time"}}}}}}
```

## Get customer earned points

> Retrieve total points earned by a customer across all programs

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/{customerId}/points/earned":{"get":{"tags":["Customers"],"summary":"Get customer earned points","description":"Retrieve total points earned by a customer across all programs","parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"},"description":"Customer ID (can be internal ID or Shopify customer ID)"}],"responses":{"200":{"description":"Customer earned points summary","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"totalEarnedPoints":{"type":"integer"}}}}}]}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}
```

## Get customer by Shopify ID

> Retrieve customer information using Shopify customer ID

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/external/{shopifyCustomerId}":{"get":{"tags":["Customers"],"summary":"Get customer by Shopify ID","description":"Retrieve customer information using Shopify customer ID","parameters":[{"name":"shopifyCustomerId","in":"path","required":true,"schema":{"type":"string"},"description":"Shopify customer ID"}],"responses":{"200":{"description":"Customer details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Customer"}}}]}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"Customer":{"type":"object","properties":{"id":{"type":"string","description":"Internal customer ID"},"shopifyCustomerId":{"type":"integer","description":"Shopify customer ID"},"email":{"type":"string","format":"email","description":"Customer email address"},"name":{"type":"string","description":"Customer full name"},"firstName":{"type":"string","description":"Customer first name"},"lastName":{"type":"string","description":"Customer last name"},"type":{"type":"string","enum":["member","guest","left"],"description":"Customer type"},"point":{"type":"integer","description":"Current available points"},"tierPoint":{"type":"integer","description":"Points used for tier calculation"},"pendingPoint":{"type":"integer","description":"Points pending approval"},"totalSpent":{"type":"number","description":"Total amount spent"},"totalEarnedPoints":{"type":"integer","description":"Lifetime earned points"},"hasPoint":{"type":"boolean","description":"Whether customer has available points"},"hasJoinedProgram":{"type":"boolean","description":"Whether customer joined loyalty program"},"orderCount":{"type":"integer","description":"Number of orders placed"},"state":{"type":"string","enum":["enabled","disabled"],"description":"Account state"},"latestActivity":{"type":"string","format":"date-time","description":"Last activity timestamp"},"notifications":{"type":"object","description":"Customer notification preferences"},"acceptsMarketing":{"type":"boolean","description":"Marketing consent"},"birthday":{"type":"string","description":"Birthday in MM/DD format"},"dateOfBirth":{"type":"string","format":"date","description":"Date of birth in YYYY-MM-DD format"},"tierId":{"type":"string","description":"Current tier ID"},"tierName":{"type":"string","description":"Current tier name"},"tierUpdatedAt":{"type":"string","format":"date-time","description":"Last tier update timestamp"},"phone":{"type":"string","nullable":true,"description":"Phone number"},"pointsRemain":{"type":"integer","description":"Points needed for next tier"},"birthMonth":{"type":"string","description":"Birth month in MM format"},"isCustomerB2B":{"type":"boolean","description":"Whether customer is B2B"},"earnSignUp":{"type":"boolean","description":"Whether customer earned signup points"},"referralCode":{"type":"string","description":"Customer's referral code"},"hasTier":{"type":"boolean","description":"Whether customer has a tier assigned"},"totalSpentCurrencyCode":{"type":"string","description":"Currency code for spending"},"createdAt":{"type":"string","format":"date-time","description":"Account creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string"},"statusCode":{"type":"integer"},"details":{"type":"object"}}},"timestamp":{"type":"string","format":"date-time"}}}}}}
```

## Update customer data by Shopify ID

> Update customer information using Shopify customer ID

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/external/{shopifyCustomerId}":{"put":{"tags":["Customers"],"summary":"Update customer data by Shopify ID","description":"Update customer information using Shopify customer ID","parameters":[{"name":"shopifyCustomerId","in":"path","required":true,"schema":{"type":"string"},"description":"Shopify customer ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dateOfBirth":{"type":"string","format":"date","description":"Date of birth in ISO 8601 format (YYYY-MM-DD)"},"birthday":{"type":"string","description":"Birthday in MM/DD format"}}}}}},"responses":{"200":{"description":"Customer updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shopifyCustomerId":{"type":"string"}}}}}]}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}
```

## Update customer VIP tier

> Update customer's VIP tier with comprehensive tier processing

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/{customerId}/tier":{"put":{"tags":["Customers"],"summary":"Update customer VIP tier","description":"Update customer's VIP tier with comprehensive tier processing","parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"},"description":"Internal customer ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tierId":{"type":"string","description":"Target tier ID"},"isInitTier":{"type":"boolean","default":false,"description":"Whether this is an initial tier assignment"},"triggerReward":{"type":"boolean","default":true,"description":"Whether to trigger tier rewards"},"adminNote":{"type":"string","description":"Admin note for the tier change activity"}},"required":["tierId"]}}}},"responses":{"200":{"description":"Customer tier updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shopifyCustomerId":{"type":"string"},"tierId":{"type":"string"},"tierName":{"type":"string"},"tierPoint":{"type":"integer"},"tierUpdatedAt":{"type":"string","format":"date-time"}}}}}]}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Customer or tier not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string"},"statusCode":{"type":"integer"},"details":{"type":"object"}}},"timestamp":{"type":"string","format":"date-time"}}}}}}
```

## Update customer VIP tier by Shopify ID

> Update customer's VIP tier using Shopify customer ID

```json
{"openapi":"3.0.0","info":{"title":"Joy Loyalty Program - REST API v2","version":"2.0.0"},"tags":[{"name":"Customers","description":"Customer data and management"}],"servers":[{"url":"https://dev-api.joy.so"},{"url":"https://api.joy.so"}],"paths":{"/rest_api/v2/customers/external/{shopifyCustomerId}/tier":{"put":{"tags":["Customers"],"summary":"Update customer VIP tier by Shopify ID","description":"Update customer's VIP tier using Shopify customer ID","parameters":[{"name":"shopifyCustomerId","in":"path","required":true,"schema":{"type":"string"},"description":"Shopify customer ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tierId":{"type":"string","description":"Target tier ID"},"isInitTier":{"type":"boolean","default":false,"description":"Whether this is an initial tier assignment"},"triggerReward":{"type":"boolean","default":true,"description":"Whether to trigger tier rewards"},"adminNote":{"type":"string","description":"Admin note for the tier change activity"}},"required":["tierId"]}}}},"responses":{"200":{"description":"Customer tier updated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"shopifyCustomerId":{"type":"string"},"tierId":{"type":"string"},"tierName":{"type":"string"},"tierPoint":{"type":"integer"},"tierUpdatedAt":{"type":"string","format":"date-time"}}}}}]}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"},"meta":{"type":"object","description":"Additional metadata such as counts and pagination"},"message":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}
```
