Skip to content

Beyond 1-to-1: Architecting Multi-Step API Orchestration

Most unified APIs are rigid 1-to-1 proxies. Discover how Truto's programmable Before and After steps handle complex API orchestration behind a single unified call.

Yuvraj Muley Yuvraj Muley · · 4 min read
Beyond 1-to-1: Architecting Multi-Step API Orchestration

When a Unified API vendor pitches you on "write once, deploy everywhere," they are usually selling you a clean interface that hides a messy reality.

The core issue is the 1-to-1 illusion: the assumption that a single POST request in your codebase will translate to exactly one POST request on the third-party SaaS platform.

In practice, third-party APIs are rarely uniform. A single logical business operation—like "Create a fully hydrated Deal" or "Onboard an Employee"—often requires a sequence of preliminary lookups, dependent network requests, and post-creation linkages.

Most unified APIs provide a rigid 1-to-1 proxy, which forces you to handle this orchestration in your own application code.

At Truto, we operate on the principle that business logic belongs in your app, but integration orchestration belongs in the integration layer. We handle this complexity using programmable Before and After steps.

The Problem: Hidden API Complexity

Consider an integration that creates a Contact in a CRM, links it to an Account, and applies a specific Tag.

If you use a standard 1-to-1 unified API, your codebase must manually orchestrate the following:

  1. Fetch dependencies: Call an endpoint to find the internal account_id for a given company name.
  2. Create the record: POST to /contacts using that account_id.
  3. Wait for the ID: Parse the response to get the new contact_id.
  4. Link the tag: Make a subsequent PUT/POST to associate the specific tag with the new contact.

This clutters your application with vendor-specific retry logic, dependency chains, and state management.

The Alternative: The Middleware Trap

To avoid polluting your main application code, you might be tempted to build a dedicated "integration middleware" service. This seems clean at first, but it quickly becomes a maintenance nightmare.

  • Latency: If you orchestrate this client-side or from a separate service, you introduce multiple network round-trips between your app, your middleware, and the third-party API.
  • Infrastructure Overhead: You now own a service that does nothing but glue APIs together. You have to manage its uptime, scaling, and security.
  • Fragility: If the third-party API changes its rate limits or pagination logic, you have to redeploy your middleware.

The Solution: A Programmable Pipeline

Truto replaces this glue code with a configuration-driven pipeline. When you make a single Unified API call, our runtime executes an ordered sequence of operations on our servers—close to the edge and optimized for speed.

You define Before steps to prepare data and After steps to handle post-processing. Truto returns the final, consolidated result to your application.

Here is the configuration for the "Create Contact" scenario described above:

{
  "before": [
    {
      "name": "lookup_account",
      "type": "request",
      "operation": {
        "method": "GET",
        "url": "/accounts",
        "query": { "name": "{{unified.company_name}}" }
      }
    }
  ],
  "request": {
    "method": "POST",
    "url": "/contacts",
    "body": {
      "name": "{{unified.full_name}}",
      "account_id": "{{steps.lookup_account.response.body.id}}"
    }
  },
  "after": [
    {
      "name": "link_tag",
      "run_if": "$exists(unified.tag)",
      "type": "request",
      "operation": {
        "method": "POST",
        "url": "/contacts/{{response.body.id}}/tags",
        "body": { "tag_name": "{{unified.tag}}" }
      }
    }
  ]
}

How It Works

  1. Before Steps (Prerequisites): The lookup_account step executes first. It queries the CRM for an account ID based on the company name. The result is stored in the global steps context ({{steps.lookup_account...}}) and injected directly into the main request payload.
  2. The Main Request: Truto executes the primary POST to /contacts using the resolved account ID. By default, the response from this request is what returns to your application.
  3. After Steps (Post-processing): Once the contact is created, the link_tag step runs. It uses the ID returned from the main request ({{response.body.id}}) to fire a second API call that tags the contact. The run_if logic ensures this only happens if a tag was actually provided.

Technical Primitives

Before and After steps are programmable primitives executed natively at the edge. You can mix and match these operation types:

  • request: Makes an HTTP call to the third-party API. It maintains full session context, applying the correct authentication tokens automatically.
  • state: Evaluates a JSONata expression against the current pipeline state. Use this to transform data mid-flight or compute values without making a network request.
  • replace_data: Swaps the primary result set with output from a specific step. This is useful if the main endpoint returns a minimal 201 response, but you want to return the full object fetched in an after step.

Control Flow

Real-world orchestration requires conditional logic. Truto's pipeline supports:

  • run_if: A JSONata expression that dictates execution. If a required custom field is missing, the step is skipped entirely.
  • delay_ms: Introduces a strict pause between steps. This is critical for rate-limited APIs that reject requests made too closely together (e.g., linking a record immediately after creation).

Observability: Debugging the Black Box

One of the biggest fears engineers have with "magic" orchestration is visibility. If a chain of 4 requests fails, how do you know which one broke?

Truto provides full execution logs for every step in the pipeline. You don't just see a 500 error; you see that the lookup_account step returned a 404, or that the link_tag step timed out.

This visibility allows you to debug integration logic as if it were running on your own local machine, without the burden of building and maintaining the logging infrastructure.

Why Programmability Matters

By pushing this orchestration down into Truto's configuration layer, you decouple your application logic from the quirks of third-party APIs.

You make one Unified API call. Truto manages the cascading network requests, data transformations, timing, and error handling.

One API call strictly equals one logical workflow. This is the difference between a unified API that is just a proxy, and one that is a true programmable runtime.

If you want to stop writing boilerplate integration code, check out our documentation to learn more.

FAQ

What are Before and After steps?
They are programmable operations that run before or after a main API request in Truto, allowing multiple chained API calls out of a single unified request.
How do Before and After steps work technically?
Steps can make preliminary or subsequent API requests, compute and transform data using JSONata state evaluations, and swap output sets—all executed dynamically by Truto.

More from our Blog