SocialHub.AI
Resources · Developer Center

POS, OMS & ERP Integration

Wire the systems you already run — your point-of-sale, order-management, and ERP — into SocialHub loyalty. Configure a managed connector for SAP, Dynamics 365, Manhattan Active Omni, IBM Sterling or Salesforce in-app — or integrate any other system through the same governed v2 REST API, authenticated with a tenant key, scoped per endpoint, and audited on every call.

One API, three system types

Every integration below is the v2 REST API over HTTPS with a Authorization: Bearer fl_live_… tenant key. Use a read-only key for reconciliation and a write-scoped key only where you award points or redeem coupons. For e-commerce platforms (Shopify, Amazon, TikTok Shop) prefer the native channel connectors — this guide is for systems without one.

Managed connectors

For five enterprise systems you don't write the integration at all — configure a connection in Settings → Data Sources(endpoint + encrypted credentials), verify it, and run a dry-run. Each connector normalizes the vendor's orders, customers and products and lands them through the very same API documented below — same scopes, same idempotency, same governed pipe. Each is labeled with how far it has been validated.

Salesforce — CRM / OMS

Fixture-validated

Order / ReturnOrder / Account-Contact / Product2 via REST + SOQL; client-credentials OAuth.

SAP S/4HANA — ERP

Fixture-validated

Sales order / business partner / product master via the OData A2X services; BTP OAuth.

Dynamics 365 — ERP / CRM

Fixture-validated

Dataverse (CE) validated; Finance & Operations scaffolded. Entra ID OAuth.

Manhattan Active Omni — OMS

In design-partner validation

Order / return / customer; mappings finalized against your tenant's Interface Mapping Document.

IBM Sterling — OMS

In design-partner validation

getOrderList / returns via the REST API envelope; status codes configured to your pipeline.

Fixture-validated = mappings built and validated against the vendor's published API, live-certified at your first deployment. In design-partner validation = mappings finalized against your tenant's integration document during onboarding. Anything not listed here integrates directly via the API below.

POS

Point-of-sale integration

The register turns a purchase into loyalty value in one call: post the sale as an order and SocialHub resolves the member (by your externalId, email, or memberId) and awards points by the program's own earn rules. Look up or create the member by your own key when you need to.

Award on a sale (post the order)

// One call: post the sale as an order. SocialHub resolves the member, applies the
// program's earn rules (tier multiplier + daily cap) and records the order — you
// don't compute points. The member is resolved by memberId > externalId > email.
POST https://flash.socialhub.ai/api/v2/orders
Authorization: Bearer fl_live_…
Idempotency-Key: pos-90871            // safe retries — one sale never awards twice
Content-Type: application/json
{
  "externalOrderId": "90871",
  "customer": { "externalId": "POS-CUST-5512" },   // or { "email": "…" } / { "memberId": "…" }
  "totalAmount": 120.00,
  "storeId": "st_…"
}
// → 200  { "data": { "awarded": 6, "balance": 1820, "memberId": "mem_…" } }
// Not a member yet → { "awarded": 0, "reason": "not-a-member" } (never auto-created).

Find or create the member

// Look up a member by your own key or email (exact match), or create one:
GET https://flash.socialhub.ai/api/v2/members?externalId=POS-CUST-5512     // or ?email=ada@acme.com
// → 200  { "data": [ { "id": "mem_…", "externalId": "POS-CUST-5512", … } ], "total": 1 }

POST https://flash.socialhub.ai/api/v2/members      // create/upsert (marketing consent stays OFF)
{ "email": "ada@acme.com", "fullName": "Ada Lovelace", "externalId": "POS-CUST-5512" }
// → 201 created  /  200 existing  (idempotent on externalId)

Redeem a coupon at the register

// Cashier scans the member's coupon code → mark it redeemed at the register.
POST https://flash.socialhub.ai/api/v2/coupons/{couponId}/redeem
Authorization: Bearer fl_live_…
// → 200  redeemed
// → 404  coupon not found / already redeemed   (treat as "do not honor")

Read back a member's balance, tier and coupons with GET /members/{id}/points, /tier and /coupons to show them at the register.

OMS

Order-management integration

For e-commerce platforms with a native connector (Shopify, Amazon, TikTok Shop), turn it on and you are done. For any other order-management system, post your order events to the Orders API — ingest auto-awards by the program rules, and refunds claw points back proportionally. Your OMS drives the calls (no inbound webhook needed).

Orders earn; refunds claw back

// On Shopify / Amazon / TikTok Shop? Use the NATIVE channel connectors (Settings →
// Channels). For any OTHER OMS, your system calls these on its own order events.
//
// order paid / fulfilled  →  ingest (auto-awards by the program's earn rules):
POST https://flash.socialhub.ai/api/v2/orders
Idempotency-Key: SO-44821
{ "externalOrderId": "SO-44821", "customer": { "email": "ada@acme.com" }, "totalAmount": 240.00 }
// → 200 { "data": { "awarded": 12, "memberId": "mem_…" } }
// Same id + a DIFFERENT amount → 409 ORDER_CONFLICT (orders are immutable).

// order returned / refunded  →  proportional points claw-back, idempotent per refund:
POST https://flash.socialhub.ai/api/v2/orders/SO-44821/refund
{ "refundId": "re_1", "reason": "returned 1 item", "amount": 80.00 }   // omit amount = full
// → 200 { "data": { "clawedBack": 4, "balance": 1816 } }

// Backfill / bulk: POST /orders/batch (≤100, 207 Multi-Status, per-item results).

Not a member yet? Ingest returns awarded:0 / reason:not-a-member (never auto-creates). Enroll them with POST /members first when you want the order to earn.

ERP

ERP & master-data integration

Keep loyalty aligned with your system of record in both directions: push your store and member master (idempotent upsert by your externalId), then reconcile incrementally with ?updatedSince= so each sync only pulls what changed.

Push the store master

// Push your store master to SocialHub (upsert by your ERP store code):
POST https://flash.socialhub.ai/api/v2/stores
{ "name": "Downtown Flagship", "externalId": "ERP-STORE-018", "city": "New York" }
// → 201 created  /  200 updated  (idempotent on externalId)
//   PUT /api/v2/stores/{id} updates a known store. GET to reconcile / pull ids.

Push members & reconcile incrementally

// Push the member master (idempotent upsert by your externalId; consent OFF unless
// you explicitly opt in). Nightly full re-push is safe — existing members update.
POST https://flash.socialhub.ai/api/v2/members/batch     // ≤100 per call, 207 Multi-Status
{ "members": [ { "email": "ada@acme.com", "fullName": "Ada Lovelace", "externalId": "ERP-7741" } ] }

// Incremental reconcile — only what changed since your last sync:
GET https://flash.socialhub.ai/api/v2/members?updatedSince=2026-06-26T00:00:00Z&limit=200
GET https://flash.socialhub.ai/api/v2/orders?updatedSince=2026-06-26T00:00:00Z       // orders too
// For governed business metrics (GMV, redemption, active members) into BI, query the
// semantic layer over MCP (metrics:read) instead of aggregating raw rows yourself.

Push the product catalog (PIM)

// Push your product catalog (idempotent upsert by your own external_id). One
// endpoint takes brands, categories, products, variants and inventory together.
POST https://flash.socialhub.ai/api/v2/catalog/import
{ "source": "erp",
  "brands":     [ { "externalId": "B-AURELIA", "name": "Aurelia" } ],
  "categories": [ { "externalId": "C-RINGS", "name": "Rings" } ],
  "products":   [ { "externalId": "P-9001", "title": "Solitaire Ring",
                    "brandExternalId": "B-AURELIA", "categoryExternalId": "C-RINGS",
                    "descriptionHtml": "<p>18k…</p>",
                    "content": [ { "externalId": "P-9001-spec", "contentType": "spec",
                                   "body": "1.0ct, 18k white gold, GIA" } ] } ],
  "variants":   [ { "externalId": "V-9001-7", "productExternalId": "P-9001",
                    "sku": "AUR-RING-7", "price": 4200 } ],
  "inventory":  [ { "variantSku": "AUR-RING-7", "locationRef": "WH-1", "available": 12 } ] }
// → 200 with per-entity {inserted,updated} + errors[] (a bad row never aborts the batch).
// On Shopify? Products map in automatically — images + rich descriptions included.
// Read back: GET /api/v2/products · /products/{id} · /categories · /brands

Batch ≤100/call (207 Multi-Status, per-item results); respect the per-key rate limit and run full re-syncs off-peak. The catalog import is external-mastered — SocialHub never writes products back to your ERP.

Auth, scopes & safety

Tenant-scoped keys

Every call carries a fl_live_ key bound to one team. Keys never cross tenants; create separate keys per integration so you can rotate one without touching the others.

Read vs write presets

Reconciliation jobs use a read-only key. Give a write scope only to the POS/OMS path that awards points or redeems coupons — least privilege per system.

Idempotency-Key

Send an Idempotency-Key header on writes (orders carry their own externalOrderId too). A retried call replays the original result; the same key with a different payload is rejected — one sale never awards twice.

Audited by default

Every API call is logged and visible under API Keys → recent activity, so an integration's writes are always traceable to a key.

Full endpoint reference: REST API · Quick Start · MCP (metrics into BI)

Integrating a backend system?

Talk to an engineer about your POS/OMS/ERP, member identity at the register, returns handling, or reconciliation jobs.

Talk to engineering