LiveRecoverVYG Developer Docs
CDP REST APIAPI Reference

Get Customer

Fetch a unified customer record — CDP profile, commerce summary, connected integrations, and subscription — by profile id, email, phone, Shopify customer id, or contact id.

GET /cdp/customers/{identifier} — fetch a single unified customer record that merges a customer's behavioral CDP profile (from the CDP) with their commerce history (from the local synced store), joined by identity. One call returns the profile core, a commerce summary, the presence of your connected integrations, and subscription status.

Requires the beta:cdp-commerce permission on your brand.

Request

GET /cdp/customers/{identifier}
Authorization: Bearer vyg_…

Path parameters

ParamTypeDescription
identifierstringA profile id, email, phone, Shopify customer id, or contact id. Classified by shape below.

The identifier is disambiguated by shape, deterministically:

ShapeInterpreted as
contains @email
starts with +phone
all digits (^\d+$)shopify_customer_id
a UUIDprofile_id, then contact_id
anything elseprofile_id (a CDP profile itemId)

A UUID is first tried as a CDP profile_id (a CDP profile itemId); if no profile matches, it is then tried as a contact_id — the local contacts.id that Customer Orders and List Orders return as customer.contact_id. This lets you join an order straight back to its customer with the id you already have. The CDP profile always takes precedence; matched_by tells you which resolved.

Response 200

{
	"identifier": "alice@example.com",
	"matched_by": "email",
	"scope": "your-shop.myshopify.com",
	"profile": {
		"id": "shopify_your-shop_5483611717768",
		"provenance": "server",
		"identity": {
			"email": "alice@example.com",
			"phoneNumber": "+14155550123",
			"firstName": "Alice",
			"shopifyCustomerId": "5483611717768",
			"shopDomain": "your-shop.myshopify.com"
		},
		"segments": ["vip", "repeat-buyer"],
		"behavior": {
			"nb_of_visits": 12,
			"first_visit": "2026-01-04T10:15:00.000Z",
			"last_visit": "2026-06-30T18:02:00.000Z"
		}
	},
	"commerce": {
		"total_spend": "200.00",
		"currency_code": "USD",
		"order_count": 2,
		"aov": "100.00",
		"first_order_at": "2026-02-20T00:00:00.000Z",
		"last_order_at": "2026-03-02T00:00:00.000Z"
	},
	"integrations": [
		{
			"id": "b1a2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
			"integration_id": "d1e3f5a7-2b4c-6d8e-0f1a-3c5e7b9d1f23",
			"is_enabled": true,
			"status": "connected",
			"connected_at": "2026-01-01T00:00:00.000Z"
		}
	],
	"subscription": {
		"status": "active",
		"active_count": 1,
		"total_count": 1,
		"next_billing_date": "2026-08-01T00:00:00.000Z"
	}
}
FieldTypeDescription
identifierstringThe identifier you requested, echoed back.
matched_bystringWhich identity key resolved the local commerce contact: email, shopify_customer_id, phone, contact_id (a direct contacts.id match), or none.
scopestring | nullYour brand's connected shop domain.
profileobject | nullThe CDP profile core, or null when no in-scope profile matched (commerce-only customer).
profile.provenancestringserver, pixel, or merged — how the profile entered the CDP.
profile.identityobjectProjected identity fields (email, phone, name, Shopify customer id, shop domain).
profile.segmentsarrayThe CDP segment ids the profile is a member of.
profile.behaviorobjectBehavioral rollups: nb_of_visits, first_visit, last_visit (each null when absent).
commerceobject | nullCommerce summary over the customer's completed orders, or null when no commerce contact resolved.
commerce.total_spend / aovstringFixed-2 decimal money strings. aov = total_spend / order_count.
commerce.order_countintegerCount of completed orders.
commerce.first_order_at / last_order_atstring | nullEarliest / latest completed-order timestamps.
integrationsarrayPresence of your connected integrations — each entry carries id, integration_id, is_enabled, status, and connected_at only. integration_id is an opaque integration id (a UUID), not a provider name; resolve it to a provider via List Integrations. No credentials or settings are ever returned.
subscriptionobjectstatus (active / inactive / none), active_count, total_count, next_billing_date.

total_spend, order_count, and aov are computed over completed orders only (matching the platform's GMV definition).

Partial matches degrade cleanly

The profile and commerce halves are joined but independent, so a partial match returns the half that exists with null on the other:

  • A profile with no matching orderscommerce: null, subscription.status: "none", and matched_by: "none" — a 200, never an error.
  • Orders with no profileprofile: null, with commerce populated. This is the shape you get when you look a customer up by their contact_id (from an order): matched_by: "contact_id", no CDP profile, commerce populated.

Example

curl -s "https://cdp.vyg.app/cdp/customers/alice@example.com" \
  -H "Authorization: Bearer vyg_your_key_here"

Errors

StatusWhen
400Missing identifier.
401Missing or invalid credential.
403Brand not enrolled in the commerce beta (beta_not_enabled), or no connected Shopify integration (integration_not_connected).
404The customer is absent from both stores — an unknown identifier or one belonging to another brand, indistinguishable by design so a brand cannot probe for another brand's customers.
405Non-GET method.
{
	"error": "not_found",
	"error_description": "Customer not found"
}

See Customer Orders for the customer's order history, and Tenant Isolation & Scope for why out-of-scope identifiers return 404.

On this page