---
title: "A shopper profile changed"
method: POST
path: "profile.updated"
tags: ["webhooks"]
---

# A shopper profile changed

`POST profile.updated` (webhook)

When an identity is attached to, moved to or rewritten on a person; not when a shopper types a contact the person already has.

## Payload

- WebhookEventWebhookProfile
  - `id` string, required: The event id, also sent as the webhook-id header; deduplicate on it
  - `type` string, required: The topic: quiz.started | quiz.finished | quiz.abandoned | identity.captured | quiz.published | experiment.started | experiment.ended | profile.created | profile.updated | export.completed | webhook.endpoint.disabled | ping
  - `created` string, date-time, required: When the event happened
  - `api_version` 'v1': The payload version
  - `data` WebhookDataWebhookProfile, required
    - `object` WebhookProfile, required
      - `id` string, required: The profile
      - `created_at` string, date-time, required: When the profile was created
      - `first_seen_at` string, date-time, nullable, required: The start of the profile's first session; null when not known
      - `last_seen_at` string, date-time, required: The latest moment the profile was seen
      - `session_id` string, nullable, required: The session that captured the identity behind this event; null when none did or its row is gone
      - `quiz_id` string, nullable, required: That session's quiz; null with it
      - `identities_from_session` string[], required: Every identity kind that session contributed so far (email | phone | shopify_customer_id), not only what this event changed
      - `urls` object, required: dashboard: the profile's page on the dashboard
      - `share_orders` ProfileShareOrder[], required: Orders bought through this shopper's shared results
        - `order_id` string, required: The Shopify order id
        - `order_name` string, nullable, required: The order's name, as #1042; null when unknown
        - `created_at` string, date-time, required: When the order was placed
        - `amount` Money, required
          - `amount` string, required: A decimal string, as "79.97"
          - `currency` string, required: ISO 4217 code
        - `quiz_id` string, nullable, required: The quiz of the session it was tied to; null when not known
        - `quiz_name` string, nullable, required: That quiz's name; null with it
        - `session_id` string, nullable, required: The session it was tied to; null when not known
        - `matched_tier` string, required: How the order was tied to the quiz session: line_item_property | cart_attribute | pixel_claim | email. The first two: the quiz put the product in the cart; pixel_claim: the checkout pixel named the session; email: the order's email belongs to the shopper
        - `via` 'retake' | 'shared_page', required: retake: bought in a session started from this shopper's shared result (session_id is that session's); shared_page: bought straight from the shared results page (session_id is the shopper's own)
        - `buyer_person_id` string, nullable, required: The buyer's profile when one is known
      - `identities` ProfileIdentity[], nullable: Endpoints with include_pii only: the profile's identities
        - `kind` string, required: email | phone | shopify_customer_id. A new kind may be added, so skip one you do not know. shopify_customer_id arrives when the shopper takes a quiz logged in to the store or places an order linked to a quiz session; its consent is always false
        - `value` string, required: The email (lowercase), the phone (E.164), or the Shopify customer as a gid://shopify/Customer/<id> GID
        - `first_seen_at` string, date-time, nullable, required: When the identity was first captured
        - `last_seen_at` string, date-time, nullable, required: The latest moment one of the shopper's sessions typed this kind of contact, never earlier than first_seen_at
        - `consent` boolean, required: True only when the shopper ticked the marketing-consent box on their newest run that showed it; anything else, including a skipped page or a quiz without the box, is false

## Acknowledgement `200`

Any 2xx within 10 seconds acknowledges the event

## Other responses

- `4XX`: 410 ends the delivery and disables the endpoint; any other 4xx but 408 and 429 ends it
- `5XX`: Retried, as are 408, 429, a timeout and a network error: seven retries over about 28 hours, then the delivery is dead

---

[API](https://skmtc.dev/octaneai/apis/octane-ai-merchant-api.md) - [All operations](https://skmtc.dev/octaneai/apis/octane-ai-merchant-api/llms.txt) - [OpenAPI document](https://skmtc.dev/octaneai/apis/octane-ai-merchant-api/revisions/dc2d1aa2b7c6?raw)
