Skip to main content
When Paygentic sits between external systems — a CRM, an ERP, a data warehouse, or any other — it needs a stable place to record “this external record is the same thing as that one.” Two thin, billing-decoupled resources own that translation: the Item and the ExternalReference.

Why these resources exist

Mapping between external systems is a pure translation — it never touches the billing engine. Rather than overload the billing Product with integration concerns, Paygentic models the mapping anchor as its own resource. The Item is the canonical “thing you sell”; the ExternalReference records each link from an Item to a record in an external system. The Item is CRM/ERP agnostic — it knows nothing about which external systems map to it. All of that lives on its ExternalReference rows, where provider is just a lowercase identifier. A common use case is bridging an upstream CRM such as Salesforce to a downstream ERP such as NetSuite, but the resources make no assumption about provider, direction, or authority — those are conventions a consumer layers on top.
The full design rationale (including the comparison to Orb’s model and the variant analysis) lives in the Item Resource — Design Rationale document on PAYG-1142.

The Item

An Item is intentionally thin — id, merchantId, name, and metadata. It carries no pricing, plan, currency, or metering, and it is independent of the billing Product.
curl -X POST https://api.paygentic.io/v0/items \
  -H "Authorization: Bearer $PAYGENTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "merchantId": "org_…", "name": "Tines Enterprise License" }'
You can create an Item with just a name and attach external references later, in any order.

The ExternalReference

An ExternalReference links an entity to its identifier in an external system. For mapping work the entityType is always item, and provider is a lowercase identifier such as salesforce or netsuite.
curl -X POST https://api.paygentic.io/v0/externalReferences \
  -H "Authorization: Bearer $PAYGENTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantId": "org_…",
    "entityType": "item",
    "entityId": "itm_…",
    "provider": "netsuite",
    "externalId": "1234",
    "externalLabel": "Cloud revenue"
  }'
The entityId must resolve to a live Item in the same merchant.

Multiple references per provider

An Item may carry several references for the same provider — for example aliases for renamed or legacy codes that all point at the same Item, or several valid downstream posting targets. Additional references beyond the primary are non-primary aliases (see below). A consumer selects the specific target it needs at the point of use.

isPrimary vs isDefault

Two independent boolean flags express two different guarantees:
  • isPrimary (default true) — at most one primary reference per (merchant, provider, externalId). This is the deduplication guarantee: an external code is primary-linked to exactly one Item. Additional non-primary references with the same code are allowed as aliases.
  • isDefault (default false) — at most one default target per (merchant, entityType, entityId, provider). This is the optional “usually post to this target” hint. Most items set no default and force a selection at the point of use.

Resolution

Resolve an external code to its Item(s) by listing with the provider + externalId filter (both must be supplied together). Resolution returns every live Item mapped to that (provider, externalId) — the canonical primary plus any non-primary aliases. The primary Item is returned first, and is unambiguously identifiable by its matching reference’s isPrimary: true (the partial-unique index guarantees at most one primary per code). An unknown code returns an empty list rather than an error. Callers that only want the canonical owner take the first result; callers reconciling renamed or legacy codes get the full alias set.
curl "https://api.paygentic.io/v0/items?merchantId=org_…&provider=salesforce&externalId=SKU_A" \
  -H "Authorization: Bearer $PAYGENTIC_API_KEY"
Fetching an Item returns its live external references in the externalReferences array. The Item itself reports no provider-specific lifecycle state — any gating (for example “is this mapped to a downstream system yet?”) is derived by the consumer from the presence of the relevant references. There is no hard stop at import time; an Item that carries only inbound references is still valid and simply has no downstream reference attached yet. See the API Reference for the full request and response schemas.