Skip to content

What is a Linked Account in Unified APIs? Architecture & Pricing Guide

A deep dive into linked account architecture in unified APIs — covering OAuth token management, tenant-specific overrides, encryption, and per-connection pricing traps.

Sidharth Verma Sidharth Verma · · 18 min read
What is a Linked Account in Unified APIs? Architecture & Pricing Guide

If you are evaluating integration infrastructure for a B2B SaaS product, you will inevitably run into the term "linked account" (sometimes called a "connected account" or "integrated account"). At first glance, the concept seems trivial: it is the database row that holds a customer's API key or OAuth token so your app can talk to their third-party software. But treating a linked account as just a static credential store is a massive architectural misstep.

The average enterprise manages 305 SaaS applications, according to Zylo's 2026 SaaS Management Index. And the connection mesh between those apps is far denser than most teams realize — Valence Security found that the average organization has over 917 hidden third-party integrations, four to five times what CISOs typically estimate.

Every single one of those connections represents a linked account. And every linked account is a living, breathing state machine that requires constant maintenance. Tokens expire. APIs go down. Customers customize their Salesforce schemas beyond recognition. If your infrastructure cannot handle these realities automatically, your engineering team will spend their days debugging silent integration failures instead of building core product features.

This guide breaks down the technical anatomy of a linked account within a unified API, how it manages complex authentication lifecycles, why tenant-specific overrides are non-negotiable for enterprise deals, and how "per-linked-account" pricing models can quietly destroy your unit economics.

What Exactly Is a Linked Account in a Unified API?

A linked account is a tenant-specific instance of a third-party integration that securely stores authentication credentials, connection state, and custom configuration overrides.

When your customer connects their Salesforce org or HubSpot account through your product, the unified API platform creates a linked account record. That record is the bridge between your application and their third-party data. Think of it this way: the integration is the template ("here's how to talk to Salesforce"), and the linked account is the instance ("here's Customer X's Salesforce org, with their credentials, their custom fields, and their specific API quirks").

flowchart TD
    A[Integration Definition<br>e.g. Salesforce] --> B[Linked Account A<br>Acme Corp's Salesforce]
    A --> C[Linked Account B<br>Globex's Salesforce]
    A --> D[Linked Account C<br>Initech's Salesforce]
    B --> E[OAuth tokens + context<br>Status: active]
    C --> F[OAuth tokens + context<br>Status: active]
    D --> G[API key + context<br>Status: needs_reauth]

A single integration definition can serve thousands of linked accounts. This is what makes unified APIs work at scale — the same Salesforce configuration handles every customer's Salesforce org, while each linked account stores that customer's unique credentials and state.

Architecturally, the linked account sits at the intersection of three distinct layers:

  1. The Tenant: The specific customer environment in your application.
  2. The Integration Definition: The global configuration describing how to talk to the third-party API (base URLs, pagination strategies, rate limits).
  3. The Unified Model: The canonical schema (e.g., "CRM Contacts") that normalizes the data.

The Anatomy of the Payload

A production-grade linked account contains far more than an access token. It encapsulates the entire context required to execute API calls on behalf of that specific tenant:

{
  "id": "acct_01H9X...",
  "tenant_id": "org_123",
  "integration_name": "hubspot",
  "status": "active",
  "authentication_method": "oauth2",
  "context": {
    "oauth": {
      "token": {
        "access_token": "[ENCRYPTED]",
        "refresh_token": "[ENCRYPTED]",
        "expires_at": "2026-10-15T14:30:00Z",
        "scope": "crm.objects.contacts.read crm.objects.companies.read"
      }
    },
    "subdomain": "api.na1.hubspot.com"
  },
  "integration_override": {},
  "unified_model_override": {}
}

The context object stores everything provider-specific: instance URLs, subdomains, tenant identifiers, and of course the credentials themselves. The override objects (covered later) are what make enterprise customization possible without forking the integration definition.

Security and Encryption at Rest

Because linked accounts hold the keys to your customers' most sensitive systems, security cannot be an afterthought. Sensitive fields within the context object — access_token, refresh_token, client_secret — must be encrypted at rest using AES-GCM or equivalent encryption. When you query the unified API for a list of linked accounts, these fields should be strictly masked. They are only decrypted in memory at the exact moment an outbound HTTP request is formulated.

Warning

If your unified API vendor returns raw tokens in list endpoints, that is a red flag worth investigating during your security review. In 2025, 22% of breaches began with stolen or compromised credentials according to Verizon's Data Breach Investigations Report — the highest of any initial attack vector. The Salesloft-Drift breach underscored this risk directly: attackers who compromised Salesloft used stored refresh tokens to access customer Salesforce instances across 700+ organizations.

The State Machine

Linked accounts are not static. They progress through a strict lifecycle:

  • connecting: The initial state when post-install validation or data synchronization is pending.
  • active: Fully operational. API calls succeed.
  • needs_reauth: The token refresh failed, or the third-party API returned a hard 401 Unauthorized. The customer must manually re-authenticate.

Tracking this state is what allows your application to show a red "Connection Broken" badge in your UI, rather than letting data syncs silently fail in the background. Silent failures are the worst kind — the integration just stops working and nobody knows until a support ticket lands.

Beyond Credentials: The Architecture of Token Management

Storing an OAuth token in a database row is the easy part. As detailed in our guide to OAuth token management, keeping it alive, valid, and secure across thousands of concurrent connections is where things get interesting.

Most third-party APIs issue access tokens that expire in 30 to 60 minutes. If you have 5,000 linked accounts, your system must execute thousands of successful token refresh operations every hour without dropping a single request. Third-party authentication platforms frequently cite automatic token management — specifically refresh, storage, and lifecycle handling — as the single highest-value feature for maintaining connected accounts.

Proactive Token Refresh

Relying entirely on on-demand refreshing (waiting until an API call is made, checking if the token is expired, and refreshing it inline) is risky. It adds latency to the request and increases the chance of failure if the provider's auth server is temporarily slow.

The better approach is to never let a token expire in the first place. A well-architected system schedules background refresh operations ahead of token expiry — typically 60 to 180 seconds before the expires_at timestamp. When a token is minted, the system schedules a task to fire within that window.

The randomization of that window matters. If you have 10,000 linked accounts whose tokens all expire on the hour, you do not want 10,000 simultaneous refresh requests hammering the provider's token endpoint. Spreading the load across a randomized window prevents thundering herd problems.

On-Demand Refresh with Concurrency Control

Proactive refresh handles the happy path, but you still need on-demand refresh as a fallback. Before every API call, the system checks whether the token will expire within a short buffer window (say, 30 seconds). If so, it refreshes before proceeding.

This introduces a severe race condition. Imagine a scenario where a linked account's token expires in 10 seconds. Suddenly, your application triggers a batch of 5 concurrent API calls (or a webhook fan-out occurs). All 5 threads check the token, see that it is expiring, and simultaneously hit the provider's /oauth/token endpoint with the exact same refresh token.

Most OAuth providers enforce strict refresh token rotation. The first request succeeds and invalidates the old refresh token. The other 4 requests fail with an invalid_grant error, permanently killing the connection and forcing the user to re-authenticate.

The standard solution is a distributed mutex lock keyed by linked account ID:

sequenceDiagram
    participant Thread1 as API Request 1
    participant Thread2 as API Request 2
    participant Mutex as Distributed Mutex Lock
    participant Provider as OAuth Provider

    Thread1->>Mutex: Acquire lock for Account A
    Mutex-->>Thread1: Lock granted
    Thread2->>Mutex: Acquire lock for Account A
    Mutex-->>Thread2: Wait (operation in progress)
    
    Thread1->>Provider: Exchange refresh token
    Provider-->>Thread1: Return new tokens
    
    Thread1->>Mutex: Release lock & update DB
    Mutex-->>Thread2: Lock granted (returns new token)
    
    Thread1->>Provider: Execute API Call 1
    Thread2->>Provider: Execute API Call 2

The first thread acquires the lock, executes the refresh, and updates the database. Subsequent concurrent threads await the resolution of the first operation, receive the newly minted token, and proceed with their API calls. Both the in-progress promise sharing and a timeout-based safety mechanism (to prevent stuck locks) are needed to make this production-ready. For a deeper walkthrough of these patterns, see our architecture guide to scalable OAuth token management.

Failure Detection and Reauth Flows

Refresh tokens can fail for reasons beyond expiry: the user revoked access, the admin changed permissions, or the provider rotated their signing keys. A production-grade linked account system needs to handle these failures with precision:

  1. Detect non-retryable errors — A 401 invalid_grant from the provider means the refresh token itself is dead. Retrying will not help. Mark the account as needs_reauth immediately.
  2. Retry transient failures — A 500 from the provider's token endpoint is temporary. Back off and retry on a schedule.
  3. Notify your customer — Fire a webhook event like integrated_account:authentication_error so the customer knows they need to reconnect. Do not let a broken integration sit silently for weeks.
  4. Auto-reactivate on success — If a subsequent API call or refresh succeeds for a needs_reauth account, flip it back to active and fire a reactivation webhook. Some token issues resolve themselves after provider-side deployments or temporary OAuth endpoint outages.

The Customization Problem: Tenant-Specific Overrides

Here is where most unified APIs quietly fall apart for enterprise customers.

A unified API normalizes data across providers into a common schema — Salesforce's FirstName and HubSpot's properties.firstname both become first_name in the unified response. This works perfectly for SMBs. It fails catastrophically in the enterprise.

Enterprise organizations heavily customize their systems of record. Customer A might store a contact's secondary phone number in a standard Salesforce field. Customer B might store it in a custom object linked via a junction table. Customer C has 200 custom fields and non-standard picklist values that completely replace the standard Contact entity. If your unified API forces a rigid schema, you lose the ability to serve any of them.

This is where the linked account becomes a configuration engine. Instead of hardcoding integration logic, the solution is per-linked-account configuration overrides — the ability to customize how data is mapped, which API endpoints are called, and what request transformations are applied, all scoped to a single customer's connection.

The Linked Account as a Configuration Engine

The linked account payload shown earlier includes two override fields: integration_override and unified_model_override. These are not decorative. They turn each connection from a passive credential store into a fully programmable execution context.

When the unified API engine processes a request, it assembles the final configuration by merging overrides from three levels:

flowchart TD
    A[Platform Base Mapping<br>Default for all customers] --> D[Deep Merge]
    B[Environment Override<br>Per-environment customization] --> D
    C[Account Override<br>Per linked account customization] --> D
    D --> E[Final Execution Config<br>Used for this specific API call]

Each level deep-merges on top of the previous, with more specific levels taking precedence. Arrays from overrides replace base arrays entirely - they do not concatenate. This means a per-account override can completely replace a list of before/after steps or a set of query parameters without inheriting unwanted entries from the base configuration.

The unified_model_override field is keyed by model, resource, and method. Here is the full nesting structure:

{
  "unified_model_override": {
    "<model_name>": {
      "<resource_name>": {
        "<method>": {
          "response_mapping": "...",
          "query_mapping": "...",
          "request_body_mapping": "...",
          "resource": "...",
          "method": "...",
          "before": [...],
          "after": [...]
        }
      }
    }
  }
}

Every field in that method object is optional. You only specify what you want to change. The engine merges your overrides on top of the base mapping, so unspecified fields fall through to their defaults.

Override Field What It Controls When You Need It
response_mapping How third-party response fields map to unified fields Customer has custom fields you need in the unified response
query_mapping How unified query params translate to third-party query params Customer's API instance requires different filter syntax
request_body_mapping How unified create/update bodies translate to third-party format Customer needs extra fields included in write operations
resource Which third-party API endpoint to call Customer uses a custom object instead of the standard one
method Which HTTP method to use Integration requires POST for search instead of GET
before Pre-request processing steps Customer needs a preliminary API call to fetch metadata
after Post-request processing steps Customer needs response enrichment from a second endpoint

This works through a three-level override hierarchy:

Level Scope Example
Platform Base All customers, all environments Default Salesforce Contact → unified contact mapping
Environment Override One customer's environment Custom OAuth app credentials for staging vs. production
Account Override One specific linked account Add Custom_Field__c to the response mapping for Acme Corp's Salesforce

Each level deep-merges on top of the previous, with more specific levels taking precedence. In Truto's architecture, these overrides use declarative JSONata expressions (a functional query and transformation language for JSON) stored as configuration data. Changing how a specific linked account's data is mapped does not require a code deployment. It is a configuration change that takes effect immediately:

// Per-account override: include Acme Corp's custom Salesforce fields
{
  "unified_model_override": {
    "crm": {
      "contacts": {
        "get": {
          "response_mapping": "response.{ 'id': $string(Id), 'first_name': FirstName, 'last_name': LastName, 'custom_tier': Custom_Tier__c, 'renewal_date': Renewal_Date__c }"
        }
      }
    }
  }
}

When a request comes in for that linked account, the execution engine merges this override on top of the base configuration. The custom fields are extracted perfectly, while every other linked account remains unaffected.

As we have explored in detail in our piece on the hidden cost of rigid unified API schemas, the ability to customize mappings per account is often the difference between closing an enterprise deal and losing it. If your unified API vendor does not support per-connection overrides, you will end up building a translation layer on top of their translation layer — defeating the entire purpose.

Managing Account-Level Overrides via the API

Overrides are stored directly on the linked account record. You manage them through the admin API by updating the unified_model_override (for data mapping changes) or integration_override (for connection-level changes like custom headers or endpoint URLs) fields.

Set an override:

curl -X PATCH https://api.truto.one/integrated-account/acct_01H9X... \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "unified_model_override": {
      "crm": {
        "contacts": {
          "list": {
            "response_mapping": "response.{ \"id\": $string(Id), \"first_name\": FirstName, \"last_name\": LastName, \"name\": $join($removeEmptyItems([FirstName, LastName]), \" \"), \"custom_tier\": Custom_Tier__c, \"renewal_date\": Renewal_Date__c }"
          },
          "get": {
            "response_mapping": "response.{ \"id\": $string(Id), \"first_name\": FirstName, \"last_name\": LastName, \"name\": $join($removeEmptyItems([FirstName, LastName]), \" \"), \"custom_tier\": Custom_Tier__c, \"renewal_date\": Renewal_Date__c }"
          }
        }
      }
    }
  }'

The response returns the full updated linked account record, including the merged override:

{
  "id": "acct_01H9X...",
  "integration_name": "salesforce",
  "status": "active",
  "unified_model_override": {
    "crm": {
      "contacts": {
        "list": {
          "response_mapping": "response.{ \"id\": $string(Id), ... }"
        },
        "get": {
          "response_mapping": "response.{ \"id\": $string(Id), ... }"
        }
      }
    }
  }
}

Read existing overrides:

curl https://api.truto.one/integrated-account/acct_01H9X... \
  -H "Authorization: Bearer <your-api-token>"

The unified_model_override field on the response shows exactly what is currently overridden for that account.

Remove an override by setting the field back to an empty object:

curl -X PATCH https://api.truto.one/integrated-account/acct_01H9X... \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "unified_model_override": {} }'

Overrides take effect immediately. The next API call made through that linked account will use the updated configuration - no restart, no deployment, no cache invalidation.

Using the CLI:

The Truto CLI exposes the same operations. To update an account's override:

truto integrated-accounts update acct_01H9X... \
  --body '{"unified_model_override": {"crm": {"contacts": {"list": {"response_mapping": "..."} }}}}'

Authoring and Testing Overrides in the Dashboard

You do not need to write overrides blind. The Truto dashboard provides a built-in API explorer for each linked account where you can test changes interactively before committing them.

The workflow:

  1. Navigate to Integrated Accounts and select the account you want to customize.
  2. Switch to the Unified API tab. This shows every resource and method available for that account's integration.
  3. Select a resource (e.g., crm/contacts) and click Try it out. The explorer executes a live API call through that linked account and shows both the unified response and the raw remote_data from the third party.
  4. Inspect the remote_data to identify the exact field paths you need. For example, you might see Custom_Tier__c: "Enterprise" in the raw Salesforce response that is not in the unified output.
  5. Write your JSONata override expression referencing those fields.
  6. Apply the override via the API or CLI, then re-run the explorer call to verify the custom fields appear in the unified response.

The /meta endpoint is especially useful here. Call GET /unified/crm/contacts/list/meta?integrated_account_id=<id> to retrieve the current mapping configuration, request body schema, and available fields for that specific account. This shows you exactly what the base mapping does, so you know what to extend.

Tip

Start by calling the unified API for the account with remote_data included (the default). Compare the raw third-party fields against the unified output. Every field present in remote_data but absent from the unified response is a candidate for a response mapping override.

Permissions, Audit Logs, and Rollback

Permissions: Override operations go through the admin API, which requires a valid API token scoped to the team that owns the integrated account. Truto's environment model provides natural isolation - linked accounts belong to environments, and API tokens are scoped to environments. A token with access to the "staging" environment cannot modify overrides on a "production" linked account.

Audit trail: Every update to a linked account record - including override changes - is tracked with a timestamp and the identity of the caller. Before applying an override to a production account, capture the current state so you can restore it if something goes wrong:

# Save the current override as a backup
curl https://api.truto.one/integrated-account/acct_01H9X... \
  -H "Authorization: Bearer <your-api-token>" \
  | jq '.unified_model_override' > override_backup.json
 
# Apply the new override
curl -X PATCH https://api.truto.one/integrated-account/acct_01H9X... \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{"unified_model_override": { ... }}'
 
# If something breaks, roll back
curl -X PATCH https://api.truto.one/integrated-account/acct_01H9X... \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d "{\"unified_model_override\": $(cat override_backup.json)}"

Rollback is straightforward because overrides are plain JSON. Restoring a previous override is just another PATCH call. For teams managing many accounts, storing override snapshots in version control (a overrides/ directory in your repo, for example) gives you full history and diff visibility.

Override Use Cases in Practice

Here are three patterns that come up repeatedly with enterprise customers:

Use case 1: Inject custom fields into the unified response

Acme Corp added Custom_Tier__c and Renewal_Date__c to their Salesforce Contact object. The base CRM unified model does not include these fields. Rather than asking every customer to receive Acme's custom fields, you override only Acme's linked account:

{
  "unified_model_override": {
    "crm": {
      "contacts": {
        "list": {
          "response_mapping": "response.{ 'id': $string(Id), 'first_name': FirstName, 'last_name': LastName, 'email_addresses': [{'email': Email}], 'custom_tier': Custom_Tier__c, 'renewal_date': Renewal_Date__c }"
        }
      }
    }
  }
}

The custom_tier and renewal_date fields now appear in the unified response for Acme's account only. Every other customer's response is unchanged.

Use case 2: Reroute to a different API endpoint

Globex stores their contacts in a custom Salesforce object called Business_Contact__c instead of the standard Contact. Override the resource field to point at the custom object:

{
  "unified_model_override": {
    "crm": {
      "contacts": {
        "list": {
          "resource": "business_contacts",
          "response_mapping": "response.{ 'id': $string(Id), 'first_name': First_Name__c, 'last_name': Last_Name__c, 'email_addresses': [{'email': Email__c}] }"
        }
      }
    }
  }
}

The resource override tells the proxy layer to call the business_contacts integration resource (which must be defined in the integration config) instead of the default contacts resource. The response mapping is also overridden because the custom object has different field names.

Use case 3: Add a pre-request step to fetch metadata

Initech's Salesforce instance uses dynamic picklist values for contact categories. Before listing contacts, you need to fetch the current picklist values so the response mapping can translate codes to labels. A before step handles this:

{
  "unified_model_override": {
    "crm": {
      "contacts": {
        "list": {
          "before": [
            {
              "name": "picklist_values",
              "type": "request",
              "config": {
                "type": "proxy",
                "resource": "contact_describe",
                "method": "get"
              }
            }
          ],
          "response_mapping": "response.{ 'id': $string(Id), 'first_name': FirstName, 'last_name': LastName, 'category_label': $lookup(step.picklist_values.fields[name='Category__c'].picklistValues, Category__c).label }"
        }
      }
    }
  }
}

The before step runs a proxy call to fetch the Contact describe metadata. The response mapping then references step.picklist_values to look up human-readable labels for each contact's category code. This entire flow is scoped to Initech's linked account - no other customer is affected.

How Linked Accounts Impact Unified API Pricing

Understanding the architecture of a linked account is important for engineering. Understanding how vendors charge for them is critical for product management.

Many unified API vendors use the linked account as their primary billing unit. The logic sounds reasonable on the surface: you pay for each customer connection you maintain. But the math gets ugly fast.

Some providers charge a flat base rate (e.g., $650/month) for a small bucket of production linked accounts (e.g., up to 10), plus a steep overage fee (e.g., $65) for every additional linked account. Here is what that looks like for a growing B2B SaaS product:

Growth Stage Customers Avg. Connections Each Total Linked Accounts Monthly Cost (at $65/account)
Early 50 2 100 ~$6,500
Growth 200 2 400 ~$26,000
Scale 500 3 1,500 ~$97,500

The structural problem is clear: per-connection pricing turns your unified API vendor bill into a tax on customer acquisition. Costs scale with connections, not with value delivered. If a customer connects five integrations but barely uses them, you pay the same as a customer who syncs thousands of records daily through a single connection.

Alternative Pricing Models

The industry has evolved beyond per-connection billing toward several approaches:

  • Per-connection — You pay for each linked account. Predictable at small scale but punishes growth. Creates perverse incentives to limit how many integrations your customers can connect.
  • Usage-based (per API call) — You pay for actual requests made. Better alignment with value, but hard to forecast. If an enterprise customer connects a massive database and triggers a high-volume historical sync, your bill becomes impossible to predict.
  • Per-integration — You pay for each type of integration enabled (e.g., "Salesforce" or "HubSpot"), regardless of how many customers connect. Costs stay flat as your customer base grows.

Truto uses per-integration pricing. Whether 10 customers or 10,000 customers connect their Salesforce accounts, the cost for the Salesforce integration stays the same. This is a direct consequence of the architecture: because Truto uses zero integration-specific code (the same generic execution engine handles every provider through declarative configuration), the marginal cost of an additional linked account is effectively zero.

That said, per-integration pricing is not universally cheaper at the smallest scale. If you only need one or two integrations and have very few customers, per-connection pricing might actually cost less. The breakeven typically happens around 15–20 linked accounts per integration — after that, per-integration pricing wins decisively.

For a detailed cost comparison across vendors and pricing models, see our 2026 unified API pricing breakdown.

Evaluating Linked Account Architecture During Vendor Selection

When you are comparing unified API platforms, the linked account architecture reveals a lot about the platform's maturity. Here is what to probe during evaluation:

Token refresh strategy — Ask whether the platform refreshes tokens proactively (before expiry) or reactively (when a call fails). Reactive-only refresh means your customers will experience intermittent failures whenever tokens expire during active use.

Concurrency handling — Ask what happens when two simultaneous API calls discover an expired token. If the vendor has not thought about this, their production reliability at scale will be poor.

Status visibility — Can you query which linked accounts are in needs_reauth state? Do you receive webhook notifications when authentication fails? If you lack this visibility, broken integrations sit undetected for weeks.

Override granularity — Can you customize field mappings per linked account, or only at the global level? This determines whether the platform can handle enterprise customers with heavily customized CRM or HRIS instances.

Credential security — Are tokens encrypted at rest? Masked in API responses? What encryption standard is used? This will come up in your SOC 2 audit.

Raw data access — Does the platform expose the original third-party response alongside the normalized data? If not, you are stuck when a customer needs a field that the unified schema does not cover. Look for a remote_data field or equivalent pass-through mechanism.

Treating Connections as Infrastructure, Not Line Items

A linked account is not merely an API key stored in a database. It is the foundational primitive of SaaS-to-SaaS communication.

It must handle cryptographic security, execute distributed mutex locks to prevent OAuth race conditions, manage its own lifecycle state, detect and recover from authentication failures, and serve as the execution context for tenant-specific data transformations. The teams that get this right treat linked accounts as infrastructure: something that should be reliable by default, secure by design, and invisible in cost as the product scales. The teams that get it wrong treat them as an afterthought — until the first enterprise deal stalls because the customer's custom Salesforce fields are not supported, or the CFO flags a five-figure monthly line item that scales linearly with ARR.

Three things to do this week:

  1. Audit your current linked account count and project it at 2x and 5x your current customer base. Does your vendor's pricing model survive that growth?
  2. Check your token refresh failure rate. If you do not have visibility into how many linked accounts are in a needs_reauth state right now, that is a gap worth closing immediately.
  3. Ask your vendor about per-account overrides. If the answer is "we don't support that" or "you'd need to use our proxy API and build your own mapping," factor that engineering cost into your total cost of ownership.

The best integration infrastructure is the kind your customers never think about. It just works, it stays connected, and it does not bankrupt you when the product takes off.

FAQ

What is the difference between a linked account and an integration in unified APIs?
An integration is the template that describes how to talk to a third-party API (e.g., Salesforce). A linked account is an instance of that integration for a specific customer, storing their unique credentials, OAuth tokens, connection context, and configuration overrides. One integration definition can serve thousands of linked accounts.
How do unified APIs handle OAuth token refreshes for linked accounts?
Production-grade unified APIs use proactive background tasks to refresh tokens 60-180 seconds before expiry, combined with on-demand refresh as a fallback. They use distributed mutex locks to prevent concurrent API calls from triggering race conditions that would invalidate the refresh token.
Can I customize field mappings for a single linked account?
Advanced unified APIs support per-account override hierarchies where you can customize response mappings, query translations, and request transformations for individual linked accounts using declarative expressions like JSONata. This is critical for enterprise customers with heavily customized CRM or HRIS instances.
Why do unified API vendors charge per linked account, and what are the alternatives?
Per-linked-account pricing ties cost to the number of customer connections, scaling linearly with customer acquisition. Alternatives include usage-based pricing (per API call), which aligns cost with value but is unpredictable, and per-integration pricing, which charges per integration type regardless of how many customers connect — keeping costs flat as you grow.
What happens when a linked account's OAuth token refresh fails?
The linked account should be marked as 'needs_reauth,' a webhook notification should be sent to your application, and the system should distinguish between retryable errors (provider 500s) and permanent failures (invalid_grant). Some platforms also auto-reactivate accounts if a subsequent refresh succeeds after a transient failure.

More from our Blog

What is a Unified API?
Engineering

What is a Unified API?

Learn how a unified API normalizes data across SaaS platforms, abstracts away authentication, and accelerates your product's integration roadmap.

Uday Gajavalli Uday Gajavalli · · 14 min read