Skip to main content

What is a unified API?

A unified API provides a single, consistent interface to interact with multiple third-party services. Instead of learning each provider’s unique schema, you define one schema that works across all of them. This guide covers one of Ampersand’s use cases: building unified APIs. You can also use Ampersand for provider-specific integrations or mix both approaches. Unlike traditional unified API providers that force you into their predefined models, Ampersand lets you design your own schema.

Why build a unified API?

  • Faster development - Add new integrations without changing application logic
  • Consistent data model - One schema regardless of source
  • No vendor lock-in - You control the schema and where data lives

How it works

1. Map objects and fields

# Map different provider objects to unified names
- objectName: account        # Salesforce
  mapToName: company
  requiredFields:
    - fieldName: name
      mapToName: company_name
    - fieldName: annualrevenue
      mapToName: revenue

- objectName: companies      # HubSpot
  mapToName: company
  requiredFields:
    - fieldName: name
      mapToName: company_name
    - fieldName: annualrevenue
      mapToName: revenue

2. Receive unified + raw data

Every webhook includes your mapped fields, non-mapped fields, and the complete provider response:
{
  "mappedFields": {
    "company_name": "Acme Corp",
    "revenue": 5000000
  },
  "fields": {
    "id": "001abc",
    "createddate": "2024-01-15T10:30:00Z",
    "systemmodstamp": "2024-08-23T14:20:07Z"
  },
  "raw": {
    "Id": "001abc",
    "Name": "Acme Corp",
    "AnnualRevenue": 5000000,
    "CreatedDate": "2024-01-15T10:30:00Z",
    "SystemModstamp": "2024-08-23T14:20:07Z",
    "Custom_Field__c": "value"
  }
}

3. Real-time updates with subscribe actions

Get webhooks when data changes (1-2 minutes latency):
subscribe:
  objects:
    - objectName: account
      destination: webhook
      inheritFieldsAndMapping: true
      updateEvent:
        enabled: always
        requiredWatchFields:
          - company_name  # Your unified field
          - revenue
// Webhook payload on update
{
  "subscribeEventType": "update",
  "mappedFields": {
    "company_name": "Acme Corp Updated",
    "revenue": 6000000
  },
  "raw": { /* full provider data */ }
}

Key architectural differences from Merge

Data persistence

Ampersand: No data storage for better security posture. Ampersand acts as the transport and transformation layer only. You control where and how to persist data. Merge: Stores all customer data in Merge servers by default. “Merge Destinations” (Enterprise) enables you to turn off storage. Why it matters: For healthcare, finance, or regulated industries, Ampersand’s transport-only architecture eliminates compliance concerns around third-party data storage.

Two-way sync

Ampersand:
  • Read: Scheduled syncs or real-time subscribe actions with field-level granularity
  • Write: Direct writes with automatic field mapping - your unified schema works for both reads and writes
  • Pattern: Subscribe + write = true bidirectional real-time sync
Merge:
  • Read: Scheduled syncs + poll after webhook notifications (model-level)
  • Write: Direct writes, but no unified mapping - you must query /meta per integration to discover required fields
  • Pattern: Polling + writes

Comparison table

FeatureAmpersandMerge
SchemaYou define itFixed common model
Raw dataAlways includedRequires include_remote_data=true flag
Data storageNo persistent storageStored in Merge cloud
Real-timeSubscribe actions (all plans)Third-party webhooks (Pro/Enterprise)
Event granularityField-level changesModel-level notifications
Write mappingAutomatic - reuses your read schemaManual - query /meta per integration

Ticketing unified API

Standardize tickets across Jira, Linear, Zendesk, and ServiceNow:
- objectName: issue
  mapToName: ticket
  requiredFields:
    - fieldName: id
      mapToName: remote_id
    - fieldName: summary
      mapToName: title
    - fieldName: status
      mapToName: status

Migration from Merge

1

Understand the persistence model

Merge: Stores your customer data; you poll their API
Ampersand: Streams data to your webhooks; you store it
Set up webhook endpoints and decide on your storage strategy (database, warehouse, etc.)
2

Use compatible templates

git clone https://github.com/amp-labs/samples.git
cd samples/unifiedCRM  # or unifiedTicketing
amp deploy --project=my-project
3

Update webhook handlers

// Merge: Poll after webhook notification
app.post('/merge-webhook', async (req, res) => {
  const contacts = await merge.crm.contacts.list({
    modified_after: lastSync,
    include_remote_data: true
  });
  await db.contacts.bulkUpsert(contacts);
  res.sendStatus(200);
});

// Ampersand: Data arrives in webhook
app.post('/webhook/contacts', async (req, res) => {
  const { mappedFields, fields, raw } = req.body.result[0];
  await db.contacts.upsert({
    ...mappedFields,
    ...fields,
    providerData: raw
  });
  res.sendStatus(200);
});
4

Add real-time with subscribe actions

subscribe:
  objects:
    - objectName: opportunity
      inheritFieldsAndMapping: true
      updateEvent:
        enabled: always
        requiredWatchFields:
          - amount
          - stage
Handle events in your webhook:
const { subscribeEventType, mappedFields } = req.body.result[0];

if (subscribeEventType === 'update' && mappedFields.stage === 'closed-won') {
  await triggerSalesWorkflow(mappedFields);
}

Complete examples