@his-her/connect
v1.3.0
Published
Shared His & Her customer hub integration library
Readme
@his-her/connect
Shared His & Her customer hub integration library.
Features
- Platform-agnostic — configure any identity component for your platform
- Identity matching — cascading lookup: platform ID → email → phone
- Reward accounts — automatic creation when a ledger is configured
- Seller onboarding sync — create Strapi service accounts and loyalty providers from Mercur seller onboarding
- Simple API — one-call
syncCustomer()or lower-level methods
Installation
# From the consuming project (e.g. hisher-multistore/backend)
yarn add @his-her/connect@file:../../libs/hisher-connectCustomer sync quick start
import { createCustomerSyncClient } from '@his-her/connect'
const sync = createCustomerSyncClient({
cdpHost: process.env.CDP_HOST || 'http://localhost:1337',
cdpApiToken: process.env.CDP_API_TOKEN,
platformIdentity: {
component: 'identity.his-and-her-store',
externalIdField: 'medusaCustomerId',
},
rewardLedger: 'reward-points',
})
// One-call sync (find-or-create + reward account)
const result = await sync.syncCustomer({
externalId: 'cus_abc123',
email: '[email protected]',
phone: '+66812345678',
firstName: 'Jane',
lastName: 'Doe',
})
console.log(result.documentId) // Strapi contact documentId
console.log(result.created) // true if new contact
console.log(result.rewardAccountCreated) // true if reward account was createdMercur seller onboarding sync
import {
createHisHerConnectClient,
createHisHerCustomerConfigFromEnv,
} from '@his-her/connect'
const hisHer = createHisHerConnectClient(createHisHerCustomerConfigFromEnv())
const result = await hisHer.features.mercurSeller.syncOnboarding({
seller: {
id: 'sel_123',
handle: 'brand_handle',
name: 'Brand Name',
email: '[email protected]',
phone: '+66123456789',
description: 'Marketplace seller',
},
ownerMember: {
id: 'mem_123',
email: '[email protected]',
},
})
console.log(result.metadata) // safe to store in Mercur seller metadataSeller sync environment
HIS_HER_CUSTOMER_STRAPI_URL=http://localhost:1337
HIS_HER_CUSTOMER_STRAPI_API_TOKEN=your-strapi-token
HIS_HER_CUSTOMER_AUTH_MODE=service-jwt
HIS_HER_CUSTOMER_SERVICE_ACCOUNT_PASSWORD=service-user-password
HIS_HER_CUSTOMER_SERVICE_ACCOUNT_ROLE_ID=3
HIS_HER_CUSTOMER_SERVICE_ACCOUNT_EMAIL_DOMAIN=service.local
HIS_HER_CUSTOMER_SERVICE_ACCOUNT_ORGANIZATION_ID=12
LOYALTY_CHANNEL_HANDLE=multistoreThe older CDP_HOST, CDP_API_TOKEN, CDP_SERVICE_ACCOUNT_ROLE_ID, CDP_SERVICE_ACCOUNT_EMAIL_DOMAIN, and CDP_MAIN_ORGANIZATION names are still supported as fallbacks.
Gift-card coupon sync
await hisHer.loyaltyCoupons.syncGiftCardCoupon({
code: giftCard.code,
channelHandle: process.env.LOYALTY_CHANNEL_HANDLE,
expiresAt: giftCard.expires_at ?? null,
})The Strapi sync endpoint stores the gift-card code in coupon sharedCode and externals[], then derives coupon ownership from the explicit providerHandle or the authenticated service user's owned loyalty providers.
Using from another platform
const sync = createCustomerSyncClient({
cdpHost: 'https://cdp.example.com',
cdpApiToken: 'token',
platformIdentity: {
component: 'identity.shopify-store',
externalIdField: 'shopifyCustomerId',
},
rewardLedger: 'reward-points',
})Lower-level API
// Find only
const found = await sync.findContact('cus_abc123', '[email protected]')
// Create
const { contact, documentId } = await sync.createContact({
firstName: 'Jane',
identities: sync.buildIdentities({ externalId: 'cus_abc123', email: '[email protected]' }),
})
// Update
await sync.updateContact(documentId, { lastName: 'Smith' })
// Reward account
await sync.ensureRewardAccount(documentId)
// Raw Strapi client
const strapi = sync.getStrapiClient()Custom logger
import { createCustomerSyncClient, type SyncLogger } from '@his-her/connect'
const logger: SyncLogger = {
info: (msg) => myLogger.info(msg),
warn: (msg) => myLogger.warn(msg),
error: (msg, err) => myLogger.error(msg, err),
}
const sync = createCustomerSyncClient(config, logger)Strapi Permissions
Setting up the correct Strapi API token is critical. The library has two usage profiles:
Frontend Usage (e.g., Storefront)
Frontend applications use CustomerSyncClient with a restricted secret token.
| Collection | Required Permissions |
|-----------|---------------------|
| contacts | find, create, update |
| ledgers | find |
| accounts | create |
Token type: Secret API token with limited collection access. No user management, no loyalty plugin access.
More details: Storefront Strapi Permissions
Backend Usage (e.g., Mercur/Multistore)
Backend services use HisHerCustomerClient with a full secret token.
| Area | Required Permissions |
|------|---------------------|
| users-permissions.user | find, create, update |
| contacts | find, create, update |
| ledgers | find |
| accounts | create |
| loyalty-pro (plugin) | Full CRUD on providers, coupons, memberships |
| sales | POST sync |
| orders | Read-only archive; deprecated sync method retained without redirect |
| auth/local | Login (for service-JWT mode) |
Token type: Secret API token with full access. Required for seller onboarding, coupon lifecycle, and Sale sync.
More details: Multistore Strapi Permissions
Full Reference
See docs/strapi-permissions.md for the complete permissions matrix, API endpoints, and environment variable reference.
