Skip to main content

Shopper Identity

Connect-once + vaulted shopper identity — let a shopper connect a login-walled store once, or vault a guest-checkout profile, so an agent can buy on their behalf without re-asking. Per-consumer, inbound, credentials never exposed.

3 min read

Shopper Identity

When an agent shops on a buyer's behalf with codespar_shop, it needs the buyer's identity at the store: a logged-in session for login-walled marketplaces (Mercado Livre, iFood), or name / CPF / address for guest checkout (VTEX retailers). Shopper identity is the per-consumer vault that captures this once and reuses it on later purchases — so the agent never re-asks, and you never handle raw credentials.

This is inbound, per-consumer identity — the shopper's own store account or checkout details. It is different from Connect Links, which run provider OAuth for accounts your integration connects (a seller's Mercado Pago, a merchant's Shopify). Connect Links vault API tokens; shopper identity vaults a store login session or a guest-checkout profile for buying.

Two mechanisms

MechanismForWhat's vaulted
Connect-onceLogin-walled stores with no buyer API (Mercado Livre, iFood)A logged-in browser session the shopper creates themselves. CodeSpar stores only an opaque context handle — the session lives in the hosted browser layer, never in CodeSpar's database.
Vaulted profileGuest-checkout stores (VTEX: Cobasi, Animale, Lojas Pompeia)The buyer's checkout identity (name, email, CPF, address), encrypted at rest and returned masked on read.

Both are driven through codespar_manage_connections and scoped per consumer (see Scoping). In both cases you never see raw credentials — the shopper completes any login themselves, and CodeSpar hands back only opaque handles or masked data.

Connect-once (login-walled stores)

A three-step flow where the shopper logs in once and CodeSpar persists the session for reuse:

 connect_start          shopper logs in            connect_finish
┌──────────┐  live_view ┌──────────────┐  done   ┌───────────────┐
│ your app │ ─────────▶ │ hosted login │ ──────▶ │ CodeSpar binds │
│ (agent)  │   url      │ (the shopper)│         │ context →      │
└──────────┘            └──────────────┘         │ (org,consumer) │
                                                 └───────────────┘
  1. connect_start returns a live_view_url (plus a session_id and context_id). Your app surfaces this URL to the shopper.
  2. The shopper opens it and logs into their own account (including 2FA). Neither your app nor the agent ever sees their credentials.
  3. connect_finish binds the now-logged-in context to (org, consumer). Later codespar_shop checkouts for that consumer reuse it automatically.
// 1) start — surface live_view_url to the shopper
const start = await session.execute("codespar_manage_connections", {
  action: "connect_start",
  server_id: "meli",
  consumer_id: "shopper_abc",
});
// show start.live_view_url to the shopper; they log in there

// 2) after the shopper confirms they're logged in
await session.execute("codespar_manage_connections", {
  action: "connect_finish",
  server_id: "meli",
  session_id: start.session_id,
  context_id: start.context_id,
  consumer_id: "shopper_abc",
});
start = session.execute("codespar_manage_connections", {
    "action": "connect_start",
    "server_id": "meli",
    "consumer_id": "shopper_abc",
})
# show start["live_view_url"] to the shopper; they log in there

session.execute("codespar_manage_connections", {
    "action": "connect_finish",
    "server_id": "meli",
    "session_id": start["session_id"],
    "context_id": start["context_id"],
    "consumer_id": "shopper_abc",
})

Vaulted profile (guest checkout)

For guest-checkout stores, vault the buyer's checkout identity once so the agent auto-fills it:

// save once (plaintext in, masked out)
await session.execute("codespar_manage_connections", {
  action: "save_profile",
  consumer_id: "shopper_abc",
  profile: {
    buyer: { firstName: "Ana", lastName: "Lima", email: "ana@example.com", document: "12345678900", phone: "+5511999999999" },
    address: { postalCode: "01310100", street: "Av. Paulista", number: "1000", neighborhood: "Bela Vista", city: "São Paulo", state: "SP" },
  },
});

// read back — PII is masked
const p = await session.execute("codespar_manage_connections", {
  action: "get_profile",
  consumer_id: "shopper_abc",
});
// p.buyer.document -> "•••00", p.buyer.email -> "a•••@example.com"
session.execute("codespar_manage_connections", {
    "action": "save_profile",
    "consumer_id": "shopper_abc",
    "profile": {
        "buyer": {"firstName": "Ana", "lastName": "Lima", "email": "ana@example.com", "document": "12345678900", "phone": "+5511999999999"},
        "address": {"postalCode": "01310100", "street": "Av. Paulista", "number": "1000", "neighborhood": "Bela Vista", "city": "São Paulo", "state": "SP"},
    },
})

p = session.execute("codespar_manage_connections", {
    "action": "get_profile",
    "consumer_id": "shopper_abc",
})
# p["buyer"]["document"] -> "•••00"

When codespar_shop runs action: "checkout" for that consumer, it loads the vaulted profile and auto-fills it (any inline buyer / address passed on the call override the stored values).

Scoping

Every vaulted identity is keyed org → consumer:

  • org comes from the API key on the request — your tenant.
  • consumer_id identifies one shopper within your tenant. Pass it on connect_start / connect_finish / save_profile / get_profile and on codespar_shop checkout. If you omit it, it defaults to the session's user id — convenient for a single-shopper session, but pass it explicitly when one tenant serves many shoppers.

A consumer's vaulted identity is only ever readable within its own org; there is no cross-tenant visibility.

Integration pattern

The intended shape is a third-party app on CodeSpar: your app owns the end-user experience (the connect button, the chat, the account screen), and CodeSpar is the credential layer underneath. Your app renders the flow and passes a consumer_id per shopper; CodeSpar holds the session / profile and never exposes raw credentials back to you. Each of your shoppers maps to one consumer_id.

Because the relationship between your app and its shoppers is yours, your app is the data controller for that shopper data and CodeSpar is the processor. If instead a person uses CodeSpar directly (their own key, shopping for themselves), they are simply their own one-tenant org — the same flow, but they hold the consumer-facing relationship directly. Choose the arrangement that matches who owns the shopper.

See also

Shopper Identity | CodeSpar