# Creating Unified APIs on Truto

> Source: https://truto.one/docs/guides/unified-apis/creating-unified-apis/

## **Overview**

Truto allows you to create Unified APIs that simplify how different applications interact. This guide will walk you through creating a Unified API for a **CRM system** using **Salesforce** as the integration example.

## **Step 1: Add a New Unified API**

### **1.1. Go to the Catalog**

1. **Log in to Truto:**
   - Navigate to your Truto dashboard.

2. **Navigate to Catalog:**
   - On the top-right, click on the `Catalog` section.

3. **Create a New Unified API:**
   - Click the `Create unified API` button.
   - ![Create Unified API](https://docs-assets.truto.one/create-unified-api.png)

### **1.2. Fill in API Details**

A popup will appear for you to enter basic information about your new API.

- **Name:** Use lowercase letters with hyphens (kebab-case).  
  *Example:* `crm`  
  *This sets the API path to `/unified/crm`.*

- **Label:** A friendly name for your API.  
  *Example:* `Unified CRM API`

- **Category:** Helps organize your API.  
  *Example:* `CRM`

- **Is Beta?:** Check this box if your API is still being tested.

![Unified API Popup](https://docs-assets.truto.one/create-unified-api-popup.png)

### **1.3. Create the API**

1. After filling in all details, click the `Create` button.
2. You'll be redirected to the `Unified API` page, displaying your newly created API.

![Available Unified API](https://docs-assets.truto.one/available-unified-api.png)


## **Step 2: Add a Resource**

A **resource** represents a specific part of your API, like "accounts" in a CRM system.

### **2.1. Add a Resource**

1. **Go to Resources:**
   - Within your Unified API page, click on the `Resources` tab.

2. **Add New Resource:**
   - Click the `Add Resource` button.

   ![Add Resource Unified API](https://docs-assets.truto.one/add-resources-unified-apis.png)

3. **Enter Resource Name:**
   - Use lowercase letters with underscores (snake_case).  
     *Example:* `accounts`

4. **Create the Resource:**
   - Click the `Add` button to finalize.

### **2.2. Configure Resource Schema**

The **schema** defines the structure of the response data your `Unified API` will handle. This is used only for documentation purposes and isn't used in validation.



1. **Edit Schema:**
   - In the `Resources` tab, select your newly added `accounts` resource.
   - Click on the `Schema` tab.
   - Click the edit (pencil) icon to modify the schema.

   ![Schema Edit](https://docs-assets.truto.one/schema-edit.png)

2. **Define the Schema:**
   - **Fields:** Specify each piece of data your API will manage.
   - **Types:** Indicate the type of data (e.g., string, integer).
   - **Descriptions:** Provide a brief explanation for each field.

    You can add the schema using the Form or in JSON.

3. **Save the Schema:**
   - After entering all fields, click the `Save` button.

   ![Add Schema Details](https://docs-assets.truto.one/add-schema-details.png)

   Note: This is how the schema will look like in `JSON` 

   ```json
   {
     "type": "object",
     "properties": {
       "id": {
         "type": "string",
         "description": "The account's unique identifier",
         "required": true
       },
       "owner": {
         "type": "object",
         "description": "The account's owner",
         "properties": {
           "id": {
             "type": "string",
             "description": "The owner's unique identifier"
           }
         }
       },
       "name": {
         "type": "string",
         "description": "The account's name"
       },
       "website": {
         "type": "string",
         "description": "The account's website"
       }
       // Add other fields as needed
     }
   }
   ```


## **Step 3: Add Methods and Configure Mapping**

The next step is to add a method, which is how the interaction happens with `Salesforce`

### **3.1. Add a Method**

1. **Add Method:**
   - Within the `accounts` resource, click the `Mapping` tab.
   - Click the `Add method` button.
   - Enter the method name in **snake_case** (e.g., `list`).
     - **Supported Methods:** `list`, `get`, `create`, `update`, `delete`, etc.

   ![Add Method](https://docs-assets.truto.one/add-method-unified-mapping.png)

2. **Save the Method:**
   - Click the `Save` button.
   - This will open the **Mapping** screen.

### **3.2. Configure Mapping Screen**

As soon as the `Method` above is saved, this screens opens up.

**Note:** These resources and their corresponding methods come from the **Integrations** (in this case, **Salesforce**).

1. **Select Resource and Method:**
   - **Resource:** Choose `accounts`.
   - **Method:** Select the method you added earlier (e.g., `list`).

   ![Mapping Screen](https://docs-assets.truto.one/resource-mapping-unified-apis.png)

## **Step 4. Define Query Mapping**
  
Translates query parameters in the Unified API call into the query supported by the underlying API. 

This step is generally optional. Use it when you want to pass custom Query Params to the underlying API that are different from what you are passing in the request.


1. **Go to Query Mapping:**
   - Click on the `Query Mapping` tab.

2. **Query Schema:**

   The Query Schema specifies what should be in the Query Parameters. Since the schema is defined in Resource Schema, you can just specify the fields from the schema that will be used in the Query and `required`, `type`, `description` will be automatically used from the Resource Schema. The Query Schema is specified in `YAML`.

   ```yaml
    name: {}
    owner: {}
    city: {}
    state: {}
    country: {}
    created_at: {}
    updated_at: {}
    last_activity_at: {}
    website: {}
    industry: {}
    number_of_employees: {}
    fields: {}
    custom_fields: {}
    search_term: {}
   ```

3. **Example:**

   A sample query input demonstrating how users can interact with the API.

   ```json
   {
     "query": {
       "search_term": "Archith",
       "name": "Archith's",
       "website": "truto",
       "include_custom_fields": ["field_1"],
       "fields": ["fields"]
     }
   }
   ```

4. **Mapping Logic:**

   Translates the Unified API's query parameters into a Salesforce-compatible SOQL query.

   ```javascript
   (
     $whereClause := query
       ? $convertQueryToSql(
         $merge([
           query
             .{
               "created_at": created_at,
               "updated_at": updated_at,
               "last_activity_at": last_activity_at,
               "name": name ? { "LIKE": "%" & name & "%" },
               "owner": owner.id,
               "city": city ? { "LIKE": "%" & city & "%" },
               "state": state ? { "LIKE": "%" & state & "%" },
               "country": country ? { "LIKE": "%" & country & "%" },
               "website": website.eq
                 ? website.eq
                 : website
                   ? { "LIKE": "%" & website & "%" },
               "industry": industry ? { "LIKE": "%" & industry & "%" },
               "number_of_employees": number_of_employees
             },
           $sift(query.custom_fields, function($v, $k) { $k ~> /__c$/i })
         ]),
         [
           "created_at",
           "updated_at",
           "last_activity_at",
           "name",
           "owner",
           "city",
           "state",
           "country",
           "website",
           "industry",
           "number_of_employees",
           $keys(query.custom_fields)
         ],
         {
           "created_at": "CreatedDate",
           "updated_at": "LastModifiedDate",
           "last_activity_at": "LastActivityDate",
           "name": "Name",
           "owner": "OwnerId",
           "city": "BillingCity",
           "state": "BillingState",
           "country": "BillingCountry",
           "website": "Website",
           "industry": "Industry",
           "number_of_employees": "NumberOfEmployees"
         },
         $merge([
           {
             "created_at": "date",
             "updated_at": "date",
             "last_activity_at": "date|yyyy-LL-dd",
             "name": "string",
             "owner": "string",
             "city": "string",
             "state": "string",
             "country": "string",
             "website": "string",
             "industry": "string",
             "number_of_employees": "number"
           },
           $keys(query.custom_fields).{ $: "string" }
         ]),
         { "LIKE": "LIKE" },
         { "noQuotesForDate": true, "escapeSingleQuotes": true }
       );
     $searchTermWhereClause := $whereClause ? " WHERE " & $whereClause;
     $searchTermCustomFields := $firstNonEmpty(query.include_custom_fields, query.fields)
       ? ", " & $join($firstNonEmpty(query.include_custom_fields, query.fields), ",");
     {
       "q": query.search_term
         ? "FIND {" & query.search_term
           & "} RETURNING Account(Id, OwnerId, Name, Description, Industry, NumberOfEmployees, Website, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry, ShippingStreet, ShippingCity, ShippingState, ShippingPostalCode, ShippingCountry, Phone, Fax, LastActivityDate, CreatedDate, LastModifiedDate"
           & $searchTermCustomFields
           & $searchTermWhereClause
           & ")",
       "where": $whereClause ? "WHERE " & $whereClause,
       "include_custom_fields": $firstNonEmpty(query.include_custom_fields, query.fields)
         ? ", " & $join($firstNonEmpty(query.include_custom_fields, query.fields), ",")
     }
   )
   ```

5. **Mapped (Result):**

   An example of how the above mapping logic transforms the input into a Salesforce-compatible query.

   ```json
   {
     "q": "FIND {Archith} RETURNING Account(Id, OwnerId, Name, Description, Industry, NumberOfEmployees, Website, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry, ShippingStreet, ShippingCity, ShippingState, ShippingPostalCode, ShippingCountry, Phone, Fax, LastActivityDate, CreatedDate, LastModifiedDate, field_1 WHERE Name LIKE '%Archith\\'s%' AND Website LIKE '%truto%')",
     "where": "WHERE Name LIKE '%Archith\\'s%' AND Website LIKE '%truto%'",
     "include_custom_fields": ", field_1"
   }
   ```

## **Step 5: Add Response Mapping**

After configuring how queries are handled, define how responses from the underlying API are transformed to fit your Unified API's structure.

### **4.1. Configure Response Mapping**

1. **Go to Response Mapping:**
   - Click on the `Response Mapping` tab.

2. **Response Schema:**

   This defines the structure of the data your API will return to users. This is specified in `YAML` and autopopulated from the Resource Schema defined above.

   ``` yaml
    type: object
    properties:
      id:
        type: string
        description: The account's unique identifier
        required: true
      owner:
        type: object
        description: The account's owner
        properties:
          id:
            type: string
            description: The owner's unique identifier
      name:
        type: string
        description: The account's name
      description:
        type: string
        description: The account's description
      industry:
        type: string
        description: The account's industry
      website:
        type: string
        description: The account's website
      number_of_employees:
        type: integer
        description: The account's number of employees
      addresses:
        type: array
        items:
          type: object
          properties:
            id:
              type: string
              description: The unique identifier of the address
            street_1:
              type: string
              description: Line 1 of the street address
            street_2:
              type: string
              description: Line 2 of the street address
            city:
              type: string
              description: The city
            state:
              type: string
              description: The state
            postal_code:
              type: string
              description: The postal code
            country:
              type: string
              description: The country
            type:
              type: string
              description: The address type
      phone_numbers:
        type: array
        items:
          type: object
          properties:
            id:
              type: string
              description: The unique identifier of the phone number
            number:
              type: string
              description: The phone number
            extension:
              type: string
              description: The extension of the phone number
            type:
              type: string
              description: The phone number type
      urls:
        type: array
        items:
          type: object
          properties:
            url:
              type: string
              description: The account's URL
            type:
              type: string
              description: The account's URL type
        description: The account's urls
      tags:
        type: array
        items:
          type: object
          properties:
            id:
              type: string
              description: The tag's unique identifier
            name:
              type: string
              description: The tag's name
        description: The contact's tags
      custom_fields:
        type: object
        description: All the custom fields present on the account
        additionalProperties: true
      last_activity_at:
        type: string
        description: The date and time of the account's last activity
        format: date-time
      updated_at:
        type: string
        description: The date and time of the account's last update
        format: date-time
      created_at:
        type: string
        description: The date and time of the account's creation
        format: date-time
   ```

3. **Provide an Example Response:**

   Provide an example raw API response from `Salesforce` so that you can verify your mapping 

   ```json
   {
     "response": {
       "attributes": {
         "type": "Account",
         "url": "/services/data/v57.0/sobjects/Account/0012w000024KwDeAAK"
       },
       "truto__Custom_Alternate_Email__c": "Archith@truto.dev",
       "Id": "0012w000024KwDeAAK",
       "IsDeleted": false,
       "MasterRecordId": null,
       "Name": "Truto-Archith-Test",
       "Type": null,
       "ParentId": null,
       "BillingStreet": "5",
       "BillingCity": "BNGLR",
       "BillingState": "KA",
       "BillingPostalCode": "560066",
       "BillingCountry": "INDIA",
       "BillingLatitude": null,
       "BillingLongitude": null,
       "BillingGeocodeAccuracy": null,
       "BillingAddress": {
         "city": "BNGLR",
         "country": "INDIA",
         "geocodeAccuracy": null,
         "latitude": null,
         "longitude": null,
         "postalCode": "560066",
         "state": "KA",
         "street": "5"
       },
       "ShippingStreet": "sdf",
       "ShippingCity": "sf",
       "ShippingState": "fsfs",
       "ShippingPostalCode": "fsfssf",
       "ShippingCountry": "sffsnull",
       "ShippingLatitude": null,
       "ShippingLongitude": null,
       "ShippingGeocodeAccuracy": null,
       "ShippingAddress": {
         "city": "sf",
         "country": "sffsnull",
         "geocodeAccuracy": null,
         "latitude": null,
         "longitude": null,
         "postalCode": "fsfssf",
         "state": "fsfs",
         "street": "sdf"
       },
       "Phone": "89845552321",
       "Fax": "5754545585544",
       "AccountNumber": null,
       "Website": "hi-triuto.one",
       "PhotoUrl": "/services/images/photo/0012w000024KwDeAAK",
       "Sic": null,
       "Industry": "Automation",
       "AnnualRevenue": null,
       "NumberOfEmployees": 2,
       "Ownership": null,
       "TickerSymbol": null,
       "Description": "Test",
       "Rating": null,
       "Site": null,
       "OwnerId": "0052w00000CkYXHAA3",
       "CreatedDate": "2024-01-09T06:07:11.000+0000",
       "CreatedById": "0052w00000CkYXHAA3",
       "LastModifiedDate": "2024-08-29T06:53:52.000+0000",
       "LastModifiedById": "0052w00000CkYXHAA3",
       "SystemModstamp": "2024-08-29T06:53:52.000+0000",
       "LastActivityDate": "2024-05-01",
       "LastViewedDate": "2024-08-29T06:53:52.000+0000",
       "LastReferencedDate": "2024-08-29T06:53:52.000+0000",
       "Jigsaw": null,
       "JigsawCompanyId": null,
       "CleanStatus": "Pending",
       "AccountSource": null,
       "DunsNumber": null,
       "Tradestyle": null,
       "NaicsCode": null,
       "NaicsDesc": null,
       "YearStarted": null,
       "SicDesc": null,
       "DandbCompanyId": null,
       "OperatingHoursId": null
     }
   }
   ```

4. **Define the Mapping Logic:**

   Transforms the raw Salesforce response into the structure defined by your Unified API's response schema.

   ```json
   response
     .{
       "id": Id,
       "owner": { "id": OwnerId },
       "name": Name,
       "description": Description,
       "industry": Industry,
       "number_of_employees": NumberOfEmployees,
       "website": Website,
       "addresses": [
         {
           "street_1": BillingStreet,
           "city": BillingCity,
           "state": BillingState,
           "postal_code": BillingPostalCode,
           "country": BillingCountry,
           "type": "billing"
         },
         {
           "street_1": ShippingStreet,
           "city": ShippingCity,
           "state": ShippingState,
           "postal_code": ShippingPostalCode,
           "country": ShippingCountry,
           "type": "shipping"
         }
       ],
       "phone_numbers": [
         { "number": Phone, "type": "phone" },
         { "number": Fax, "type": "fax" }
       ],
       "last_activity_at": LastActivityDate,
       "created_at": CreatedDate,
       "updated_at": LastModifiedDate,
       "custom_fields": $sift($, function($v, $k) { $k ~> /__c$/i and $boolean($v) })
     }
   ```

   **Explanation:**

   - **id:** Maps Salesforce's `Id` to your API's `id`.
   - **owner:** Extracts `OwnerId` from Salesforce and nests it under `owner.id`.
   - **addresses:** Combines billing and shipping addresses into a single array, distinguishing them by type.
   - **phone_numbers:** Includes both `Phone` and `Fax` numbers with their respective types.
   - **custom_fields:** Filters and includes only custom fields from Salesforce that end with `__c` and have valid values.

5. **Check the Mapped (Result):**

   This is the result of your `Response Example` above transformed through the `Response Mapping`. Use it to verify that the mapping is correct.

   ```json
   {
     "id": "0012w000024KwDeAAK",
     "owner": {
       "id": "0052w00000CkYXHAA3"
     },
     "name": "Truto-Archith-Test",
     "description": "Test",
     "industry": "Automation",
     "number_of_employees": 2,
     "website": "hi-triuto.one",
     "addresses": [
       {
         "street_1": "5",
         "city": "BNGLR",
         "state": "KA",
         "postal_code": "560066",
         "country": "INDIA",
         "type": "billing"
       },
       {
         "street_1": "sdf",
         "city": "sf",
         "state": "fsfs",
         "postal_code": "fsfssf",
         "country": "sffsnull",
         "type": "shipping"
       }
     ],
     "phone_numbers": [
       {
         "number": "89845552321",
         "type": "phone"
       },
       {
         "number": "5754545585544",
         "type": "fax"
       }
     ],
     "last_activity_at": "2024-05-01",
     "created_at": "2024-01-09T06:07:11.000+0000",
     "updated_at": "2024-08-29T06:53:52.000+0000",
     "custom_fields": {
       "truto__Custom_Alternate_Email__c": "Archith@truto.dev"
     }
   }
   ```

  Once done, save your mapping by clicking on `Save`. This will save your Unified API mapping for the resource.
  You can test the Unified API created after connecting an [Integrated Accounts](/docs/guides/integrated-accounts/making-api-calls.md). 

## **Static Mapping**

Sometimes, an API endpoint always returns the same, unchanging data (like a predefined list of options or a fixed configuration). In such cases, instead of making unnecessary API calls to fetch the same static data every time, you can use **Static Mapping**.

Static Mapping allows you to configure a response directly in the Unified API, so the response is sent without actually making any API calls. This is especially useful for **list** or **get** endpoints where the data doesn't change often or at all - you can enable **Static Mapping** for these methods.
### **How to Enable Static Mapping**

1. **Navigate to the Response Mapping Tab**  
   - Go to the resource you're working on (e.g., `/list-options` or `/configurations`).  
   - Open the **Response Mapping** section for that resource.

2. **Enable Static Mapping**  
   - Look for the **Static Mapping** toggle.  
   - Turn it **on** to activate static mapping for this resource.  

3. **Define the Static Response**  
   - Once enabled, you can define the static response that will be returned every time this endpoint is called.  
   - Example:  
     ```json
     {
       "options": [
         { "id": 1, "name": "Option A" },
         { "id": 2, "name": "Option B" },
         { "id": 3, "name": "Option C" }
       ]
     }
     ```

Once enabled, it should look like :      
![Static Mapping](https://docs-assets.truto.one/static-mapping.png)



4. **Save Your Configuration**  
   - Save your changes, and the Unified API will now return the static response whenever this endpoint is called.

---

### **When to Use Static Mapping?**

- **List or Get Endpoints:** For endpoints that return predefined or rarely changing data, such as dropdown options or fixed settings.
- **No Backend Dependency:** If you don't want the response to rely on a API call.
- **Faster Responses:** Reduces latency since no actual API request is made.


## Error Mapping

In case the underlying API returns an error, you can define a custom mapping to standardize the error structure for your Unified API consumers.

### Configure Error Mapping

1. Go to **Error Mapping**:
   - Click on the **Error** tab.
2. **Error Example** (JSON):

   ```json
   {
     "message": "Something went wrong",
     "errorCode": 4001
   }
   ```

### Error Mapping

Error mapping should return an object that includes the following:

- **Error Message (`message`)**: The main error message describing what went wrong.
- **Metadata (`metadata`)**: Optional additional details about the error, such as timestamps, request IDs, or other context.
- **Status (`status`)**: Optional HTTP status code associated with the error, e.g., 400 for a bad request or 500 for an internal server error.

#### Example:

```json
{
  "error": "ValidationError",
  "message": "Invalid input provided",
  "status": 422,
  "metadata": {
    "field": "email",
    "errorCode": "INVALID_EMAIL_FORMAT",
    "timestamp": "2025-01-24T12:34:56Z"
  }
}
```

![Error Mapping](https://docs-assets.truto.one/error-mapping.png)

#### View Available Bindings
Use platform-specific bindings to reference error details, status codes, etc.

### Mapped Error (Result)

Applying your mapping to the example error might produce the following result:

```json
{
  "message": "Invalid input provided",
  "metadata": {
    "field": "email",
    "errorCode": "INVALID_EMAIL_FORMAT"
  }
}
```

## Request Header Mapping

You can define how your Unified API injects or transforms headers before sending them to the underlying API.

### Configure Request Header Mapping

1. Go to **Request Header**:
   - Click on the **Request Header** tab.
2. **Request Header Example** (JSON):

   ```json
   {
     "x-truto-header": "abc123",
     "x-truto-custom-header": "myValue"
   }
   ```

   This is an example of the headers you may want to send.

### Request Header Mapping

- **The mapping should return an object** where the key-values contain the header name and the value.
  
  Example JSONata mapping:
  
  ```jsonata
  {
    "header": x-truto-header
    "customHeader": x-truto-custom-header
  }
  ```

- **View available bindings**: Use platform-specific bindings to reference dynamic values if needed.
- **Beautify JSONata** (optional): Prettifies the expression for easier readability.

### Mapped Header (Result)

After applying your JSONata mapping, you’ll see a preview of what headers will be sent. For example:

```json
{
  "header": "abc123",
  "customHeader" : "myValue"
}
```

![Request Header Mapping](https://docs-assets.truto.one/request-mapping.png)

## Response Header Mapping

You can define how headers returned by the underlying API are transformed or exposed back to the consumer of the Unified API.

### Configure Response Header Mapping

1. Go to **Response Header**:
   - Click on the **Response Header** tab.
2. **Response Header Example** (JSON):

   ```json
   {
     "some-internal-header": "some-value",
     "some-other-header": "sessionid=123456"
   }
   ```

### Response Header Mapping

- **The mapping should return an object** where the key-values contain the header name and the value.
  
  Example JSONata mapping:
  
  ```jsonata
  {
    "x-truto-header": some-internal-header
  }
  ```
  
- Modify the returned header names or filter them as needed.

### Mapped Header (Result)

For instance, if your mapping logic only passes through certain headers:

```json
{
  "x-truto-header": "some-value"
}
```

You’ll see the final headers that will be returned to the client in this preview.

![Response Header Mapping](https://docs-assets.truto.one/response-mapping.png)


## **Before Steps**

Before Steps are actions that run **before** the main request is made by the Unified API. Think of Before Steps as a way to prepare your request with extra data, replace missing fields, or add logic to handle specific conditions.


### **How to Set Up Before Steps**

1. **Choose the Type of Step**  
   There are three types of Before Steps you can configure:
   - **Request:** Fetch additional data.
   - **State:** Store the data for later use in `Before Steps`.
   - **Replace Data:**  Replace the data of the Before Steps in the request with a `State` defined.

### **Detailed Step Types**

#### **1. Unified API (Fetch Additional Data)**  
Use this step to call another Unified API resource and fetch additional data before the Unified API call.  
- **When to Use It:**  
  If your request requires data from another resource, like fetching interview details before querying candidates.

- **Setup:**
  - **Name:** Enter a name for the step.  
    Example: `Fetch Interview Details`
  - **Run Conditionally:** Enable this to only run the step when needed.
  - **Run If (Optional):** Add a **JSONata expression** to decide whether the step should run.  
    Example:  
    ```jsonata
    $exists(query.interview_id)
    ```
    This step will run only if `interview_id` exists in the query.
  - **Is JSONata Expression?:** Enable this to specify a `JSONata` expression for the `Request`.
      You should specify the following attributes in the `JSONata` expression :
      - `resource` - The name of the resource to call
      - `method` - The method which can be a **get**, **list**, **create**, **update**, **delete** 
      - `type` - The type of the request which is, `Unified` or `Proxy`.
  
    You can also use the available [Before/After JSONata Bindings](/docs/guides/unified-apis/mapping-bindings#before-after-steps) to send, access, and modify `body`, `query` or `id` values.

  Alternatively, you can select the following options :
  - **Request Type:** Select the `Unified` or `Proxy` API.
  - **Resource to Fetch:** Select the resource (e.g., `interviews`).
  - **Method to Call:** Choose the method (e.g., `get` or `list`).
  - **Enter ID (if needed):** Provide the ID for the resource to fetch. Used in `get` methods.
  - **Query Parameters:** Add any parameters needed in JSON format.  
    Example:  
    ```json
    {
      "include_details": true
    }
    ```
  - **Request Body (if applicable):** Specify the body in JSON format.
---

#### **2. State**  
Use this to store the data for later use in `Before Steps`.

- **Setup:**
  - **Name:** Enter a name for the step.  
    Example: `Set Default Priority`
  - **Run Conditionally:** Enable this to only run the step when needed.
  - **Run If (JSONata):** Provide a JSONata expression that returns `true` or `false` to determine whether the step should run.  
    Example:  
    ```jsonata
    $not($exists(query.priority))
    ```
    This step will run only if the `priority` field is missing.
---

#### **3. Replace Data**  
Use this step to replace the data of the Before Steps in the request with a state you defined.  

- **Setup:**
  - **Name:** Enter a name for the step.  
  - **Run Conditionally:** Enable this to only run the step when needed.
  - **Run If (JSONata):** Provide a JSONata expression that returns `true` or `false` to determine whether the step should run.  
  - **State Name:** Specify the name of the `state` defined above to replace.  

The `Before Steps` screen looks like -

![Before Steps](https://docs-assets.truto.one/before-steps.png)


## **After Steps**

After Steps are actions that run **after** the main request is made by the Unified API. Think of After Steps as a way to modify your request with extra data, replace missing fields, or add logic to handle specific conditions before returning the data to the user.


### **How to Set Up After Steps**

1. **Choose the Type of Step**  
   There are three types of After Steps you can configure:
   - **Request:** Fetch additional data.
   - **State:** Store the data for later use in `After Steps`.
   - **Replace Data:** Replace placeholders or incomplete fields in the request with predefined values.

### **Detailed Step Types**

#### **1. Unified API (Fetch Additional Data)**  
Use this step to call another Unified API resource and fetch additional data after the Unified API call.  
- **When to Use It:**  
  Say, for example, in a `PATCH` request, if the underlying API only returns the `id` of the updated resource, you can use after steps to fetch the complete details. After the PATCH request is processed, an after step can make a GET call to retrieve the full resource data and return the complete response to the user
- **Setup:**
  - **Name:** Enter a name for the step.  
    Example: `Fetch Interview Details`
  - **Run Conditionally:** Enable this to only run the step when needed.
  - **Run If (Optional):** Add a **JSONata expression** to decide whether the step should run.  
  - **Is JSONata Expression?:** Enable this to specify a `JSONata` expression for the `Request`.
      You should specify the following attributes in the `JSONata` expression :
      - `resource` - The name of the resource to call
      - `method` - The method which can be a **get**, **list**, **create**, **update**, **delete** 
      - `type` - The type of the request which is, `Unified` or `Proxy`
    
    You can also use the available [Before/After JSONata Bindings](/docs/guides/unified-apis/mapping-bindings#before-after-steps) to send, access, and modify `body`, `query` or `id` values.

  Alternatively, you can select the following options :
  - **Resource to Fetch:** Select the resource (e.g., `interviews`).
  - **Method to Call:** Choose the method (e.g., `get` or `list`).
  - **Enter ID (if needed):** Provide the ID for the resource to fetch. Used in `get` methods.
  - **Query Parameters:** Add any parameters needed in JSON format.  
    Example:  
    ```json
    {
      "include_details": true
    }
    ```
  - **Request Body (if applicable):** Specify the body in JSON format.

---

#### **2. State**  
Use this to store the data for later use

- **Setup:**
  - **Name:** Enter a name for the step.  
    Example: `Set Default Priority`
  - **Run Conditionally:** Enable this to only run the step when needed.
  - **Run If (JSONata):** Provide a JSONata expression that returns `true` or `false` to determine whether the step should run.  
    Example:  
    ```jsonata
    $not($exists(query.priority))
    ```
    This step will run only if the `priority` field is missing.
---

#### **3. Replace Data**  
Use this step to replace the data of the After Steps in the request with a state you defined.  

- **Setup:**
  - **Name:** Enter a name for the step.  
  - **Run Conditionally:** Enable this to only run the step when needed.
  - **Run If (JSONata):** Provide a JSONata expression that returns `true` or `false` to determine whether the step should run.  
  - **State Name:** Specify the name of the `state` defined above.
    
The `After Steps` screen looks like -

![After Steps](https://docs-assets.truto.one/after-steps.png)


## Truto Notes 

This section is a space where the Truto team jots down important details, limitations, and potential pitfalls specific to this resource in our Unified Model. You can also add details here to note important details.

### What You Can Write Here

- **Key Characteristics**:  
  Describe what makes this resource unique or any quirks it might have. This helps set expectations and provides context.

- **Usage Tips**:  
  Share simple tips and best practices on how to use this resource effectively. For example, mention common pitfalls or suggest smoother ways to handle certain tasks.

- **Limitations**:  
  Point out any known limitations or constraints. If the underlying API has restrictions that affect this resource, note them here in plain language.

- **Troubleshooting Advice**:  
  Offer friendly guidance on what to do if things don't work as expected. This can include hints on where to look for errors or how to fix common issues.

- **Reminders and Warnings**:  
  Add any reminders or gentle warnings that can help users avoid mistakes or understand important considerations when interacting with the resource.

- **General Observations**:  
  Write down observations or thoughts that might be useful for anyone working with or maintaining this resource in the future.

![Truto Notes](https://docs-assets.truto.one/truto-notes.png)
