Staff & contacts
Sync the people at a merchant, the owner and staff users, as contacts.
The Partner API tells you a shop installed your app, but nothing about the people in it. On install you only ever have the account owner; staff members only become visible to your app as they use it. This endpoint lets you push those people to PartnerConsole, where they appear as contacts on the customer, usable in flows and campaigns.
Getting the people from Shopify
Shopify only reveals a staff member's name and email through a token exchange for an online access token, which returns an associated_user:
- Embedded apps: exchange the App Bridge
id_tokenfor an online token; readassociated_user. - Non-embedded apps: request an online access token during OAuth; the grant response carries
associated_user.
Either way you end up with { id, first_name, last_name, email, email_verified, account_owner, locale }. That's what you forward to us.
There is no "list all staff" for a standard app, that needs the read_users scope (Shopify Plus only). So you capture staff incrementally, one per session as each person opens your app. The owner/installer you get on install; the rest accrue over time. This is a Shopify constraint, every app faces it.
You own the data, or we do — your choice
The endpoint is built so either model works, with no change on our side:
- You store staff in your own system and sync to us. Keep your own table, push the full roster whenever it changes with
reconcile: true(we add present people and remove absent ones, so deletes propagate). - You send straight to us and don't store anything. Fire each staff member as you see them (default upsert), and read them back with
/customerif you need them. We become your system of record.
Both converge to the same state because we dedupe on the Shopify user id (id), not email, so re-sending the same person is always safe.
Send one, or the whole roster
# Incremental: one person, fire-and-forget per session
curl -X POST https://api.partnerconsole.co/v1/staff \
-H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"myshopifyDomain": "example.myshopify.com",
"staff": [{
"id": "gid://shopify/StaffMember/123",
"firstName": "Ada", "lastName": "Lovelace",
"email": "[email protected]", "accountOwner": true, "installer": true
}]
}'# Full reconcile: your complete roster; anyone not listed is removed
curl -X POST https://api.partnerconsole.co/v1/staff \
-H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{
"myshopifyDomain": "example.myshopify.com",
"reconcile": true,
"staff": [ {"id": "…", "email": "[email protected]"}, {"id": "…", "email": "[email protected]"} ]
}'How they appear
- Each staff member becomes a contact on the customer, keyed on the Shopify user id, with a role derived from
accountOwner(owner) /installerand tags you send. - Contacts a human added by hand in the console are marked
manualand are never touched by a reconcile, only app-sourced contacts are reconciled. emailcan change; because we key on the stable user id, a renamed email updates the same contact instead of creating a duplicate.
When to call it
- On install, with the owner/installer flagged.
- On each embedded page load (or online-token refresh) for the current user, cheap and idempotent.
- On a schedule with
reconcile: trueif you maintain your own roster and want deletes to propagate.