Chidi Okwudire

Chidi Okwudire

Technology Practice Leader

NetSuite Other Relationships: 3 Working Approaches for Bulk and Automated Workflows

ERP NetSuite Technical



This article is relevant if you need a single NetSuite entity to hold multiple roles (e.g. customer and vendor) and you want a practical way to establish Other Relationships in bulk or through automation.

TL;DR Summary

NetSuite’s Other Relationships feature allows one entity to behave as multiple record types. A common example is when the same business party must act as both a customer and a vendor. The feature is easy enough to activate in the UI, but the real challenge begins when you need to do it in bulk or automate it going forward.

In practice, there are three viable approaches. A client-side URL pattern is useful for one-off bulk updates. record.transform is a strong option when the target other relationship does not yet exist. Entity deduplication is the right answer when both entity types already exist and need to be combined into a single underlying entity. The confusion is not whether this can be done; it can. The confusion is understanding what works, what fails, and which method fits the situation.

Decision tree diagram for establishing a NetSuite Other Relationship, branching by whether the relationship exists and whether the task is one-off or recurring

Background

NetSuite’s Other Relationships feature, also known as “Records as Multiple Types”, allows a single entity record to act as multiple types. For example, one record can function as both a customer and a vendor, or as a vendor and partner, while retaining the same internal ID. That is a powerful capability when a business party needs to participate in multiple transactional roles. The feature is currently available on customer, partner, vendor, and other name entity types.

NetSuite entity Other Relationship types diagram showing customer, vendor, partner, and other name

This relationship is easy to establish in the UI. You create the initial entity record, then use the Other Relationships icon on the Relationships subtab to associate the record to another entity type.

NetSuite Other Relationships icon on the Relationships subtab of a customer record

The result is one entity that behaves as multiple entity record types.

The trouble starts when the task must be performed in bulk or on an ongoing basis. The UI approach is not a sustainable solution for a large number of records, much less for a recurring business rule. In a recent client engagement, the same entity needed to participate in both accounts receivable and accounts payable transactions. Specifically, certain customers meeting defined criteria also needed to function as vendors. This is a perfect use case for the Other Relationships feature. With close to 100 records to process initially, doing this by hand was not a responsible use of skilled consultant capacity. Moreover, the business requirement was to establish the link as new eligible customers get created in the future.

Naturally, the next thought is CSV import, mass update, or SuiteScript. Unfortunately, Other Relationships cannot be established via CSV import or mass update at the time of writing. Thus, we are left with scripting. That is where things become murky. There are several useful articles on the topic, but it takes effort to determine which patterns are still dependable and which details are hidden in comments or implied through examples.

These were the key references I reviewed:

 

While each of these articles offered a piece of the puzzle, I still needed to synthesize and iterate. This is not a critique of those articles. They were helpful and likely accurate when written. The problem is that the working options are not obvious when you are trying to solve the problem now, especially if you are relying on search results, old threads, or AI-generated code. In my own testing, AI tools often assumed that otherrelationships behaved like a normal body field or editable sublist and produced code that did not work at all. That experience inspired this article.

NetSuite Other Relationships: The Practical Paths

The most important insight is that this is not one problem; it is three.

You may need to create a missing target relationship for an existing entity. You may need to automate that behavior every time a source record is saved. Or you may already have both sides, such as a customer and a vendor, and need to combine them into one identity. Those scenarios require different approaches.

Choosing the Right Approach

Before delving into the technical details of each approach, it is useful to understand which to use when. The decision tree is simple:

Decision tree for choosing a NetSuite Other Relationships approach: URL pattern, record.transform, or deduplication merge
  • One-off update: Consider the browser console with the URL pattern as it is quick and requires minimal setup.
  • Recurring automation: Use a server-side script (e.g., a User Event script) that implements one or both automation paths:
    • If the other entity does not exist or transformation is not supported for the target entity type; transform.
    • If the other entity already exists, merge.

Solution Details

Approach 1: Client-side Using the URL Pattern

This approach relies on crafting a URL with the right parameters to get NetSuite to work the same way it does when someone manually sets up the Other Relationships in the UI. It is officially supported in the sense that it is backed by SuiteAnswers ID: 41804, but it still feels operationally brittle because it depends on URL patterns that could change without notice. For that reason, we consider this a practical tool for one-off work, not the best foundation for a long-term automation strategy.

The generic URL pattern is:

https://<accountID>.app.netsuite.com/app/common/entity/company.nl?e=T&fromtype=[FROM_TYPE]&totype=[TO_TYPE]&target=s_relation:otherrelationships&label=Other+Relationships&id=4953

Supported values for FROM_TYPE and TO_TYPE are generally intuitive, except for the Customer entity, which diverges slightly:

  • custjob for Customer
  • vendor for Vendor
  • partner for Partner
  • othername for Other Name

Once a valid URL is established, a simple code snippet can be run in the browser console to invoke the URL and get the job done. The catch is that invoking the URL causes NetSuite to redirect to the newly linked other relationship entity. That means a naïve browser console approach can only handle one record at a time before the redirect interrupts the process. We solve for that by running asynchronously, thus allowing us to process a collection of records as illustrated below.

Here’s a sample code snippet:

/**
* Snippet to bulk configure other relationship in bulk.
* Target entities are driven by a search.
* This should be run in the browser console on a NetSuite record page
* (to ensure 'require' and dependencies are loaded)
*
* @author Chidi Okwudire (AI-augmented)
* @license MIT
*/
require(['N/search'], function (search) {

  // ── Configuration ──────────────────────────────────────────
  const SEARCH_ID = 'customsearch_cust_missing_vendor_rel';
  const FROM_TYPE = 'custjob';
  const TO_TYPE   = 'vendor';
  // ───────────────────────────────────────────────────────────

  function buildUrl(fromId) {
    return '/app/common/entity/company.nl?' + new URLSearchParams({
      e: 'T',
      fromtype: FROM_TYPE,
      target: 's_relation:otherrelationships',
      label: 'Other Relationships',
      id: fromId,
      totype: TO_TYPE
    });
  }

  async function run() {
    const resultSet = search.load({ id: SEARCH_ID }).run();
    const fromIds = [];

    resultSet.each(function (result) {
      fromIds.push(result.id);
      return true;
    });

    let ok = 0;
    let err = 0;

    for (const fromId of fromIds) {
      try {
        const response = await fetch(buildUrl(fromId));
        if (!response.ok) {
          throw new Error(`HTTP ${response.status} ${response.statusText}`);
        }
        console.log('[OK]', fromId);
        ok++;
      } catch (e) {
        console.error('[ERR]', fromId, e && e.message ? e.message : e);
        err++;
      }
    }

    console.log(`Done: ${ok} linked, ${err} errors.`);
  }

  run();
});

Note that this method assumes that the target Other Relationship does not already exist. If it does, the process fails with an Internal Server Error (HTTP 500). It is also important to execute this snippet on a NetSuite page where the necessary dependencies are loaded such as a single vendor or customer in view mode. Attempting to execute on a page like the customer list or saved search results will result in an error like: Uncaught ReferenceError: require is not defined.

For our use case, this was a very practical way to establish the Other Relationship for the existing set of customers, thereby confirming that the approach still works and solving for bulk execution before moving into fully automated mode.

Approach 2: Using record.transform

When the target other relationship does not yet exist and you want to automate the process on an ongoing basis, record.transform is the cleaner option for the supported entity record types. For example, a User Event script may be deployed to the target entity record type to automatically establish the relationship upon creation or update. Here’s the script pattern:

record.transform({
    fromId: id, // internal ID of an existing record
    fromType,   // e.g. record.Type.CUSTOMER
    toType      // e.g. record.Type.VENDOR
});

Although incorrectly reported as an unsupported feature in some discussions, this is a valid approach, confirmed by testing and backed by the official documentation that currently lists vendors and customers as supported transformation types. There’s a catch though: partner and other name entity relationships cannot be established in this way. In testing a partner-to-vendor relationship, an INVALID_RCRD_TRANSFRM occurred with the message “That type of record transformation is not allowed. Please see the documentation for a list of supported transformation types”. This behavior is consistent with the documentation.

I also found an interesting nuance involving entity IDs: In accounts where entity IDs are auto-generated, the transform can fail with an error like:

“You may only change the name from the CustJob version of this record”

The fix is to ensure that the transformed record’s entityid exactly matches the source entity before saving. For example, if the source customer record has entity ID CUS-00298 Smith Inc., during the transformation, it needs to explicitly be stripped down to CUS-00298 for the operation to succeed.

Finally, this approach only works if the target relationship does not yet exist. Otherwise, the transformation fails with the message: “This entity already exists.”

Approach 3: Using the Native Entity Deduplication Feature

This approach is the least intuitive, but it becomes essential when both target entities already exist or when approach 2 is not viable because the target record type is unsupported (e.g., vendor to partner linkage).

The pattern is simple, once understood:

  1. Decide which entity will survive as the master record.
  2. Note the type of record that will be consumed in the merge.
  3. Submit a deduplication task that runs in the background.

Here is the sample function/pattern for linking an existing vendor into a surviving customer:

const linkExistingVendor = (custId, vendorId) => {
       const fn = `linkExistingVendor.${custId}.${vendorId}`;
       log.debug(fn, 'In');
       const linkTask = task.create({ taskType: task.TaskType.ENTITY_DEDUPLICATION });
       linkTask.entityType          = task.DedupeEntityType.VENDOR; // Must match type of the recordIds parameter
       linkTask.dedupeMode          = task.DedupeMode.MERGE;
       linkTask.masterSelectionMode = task.MasterSelectionMode.SELECT_BY_ID;
       linkTask.masterRecordId      = custId; // Survives the merge
       linkTask.recordIds           = [vendorId];
       const taskId = linkTask.submit();
       log.debug(fn, `Out - taskId ${taskId}`);
   };

Again, some examples online have the pattern mixed up. The entityType needs to match the entity type being consumed through recordIds, not the surviving master. If you get that wrong, you may end up with a cryptic error like “Failed to resolve vendor relationship for Customer 30573: Failed to submit job request: Inserted entity is not of declared primary flavor. nKey:30572.”

A Consolidated Approach

In our use case, we combined approaches #2 and #3 into a single user event script that, upon creation or editing a customer record, detects if the vendor link is missing via a saved search pattern we will explain shortly. If the link is missing, it checks whether a vendor with a matching entity ID exists in which case it uses the deduplication approach to combine them. Otherwise, it uses record.transform to establish the link. The outcome is a hands-off automation that runs in the background and ensures entities are correctly configured.

Using the snippets and information provided in this article, the adept reader (human or AI agent) should be able to produce similar solutions.

On a tangential note, if you need an automated solution for high-volume entity deduplication, check out my earlier piece titled Beyond Native Tools: A Scalable Architecture for NetSuite Entity Deduplication.

Related Considerations

How to Identify Entities Missing a Target Other Relationship

Saved searches offer an easy way to expose entities missing the target relationship. The Other Relationships filter is the key, as illustrated below using a customer search that exposes customers missing the vendor relationship. Naturally, other business-specific criteria may be added as needed.

NetSuite saved search criteria filtering customers missing the vendor Other Relationship

The following is the equivalent search definition in SuiteScript:

const customerSearchObj = search.create({
  type: "customer",
  filters:
  [
     ["otherrelationships","noneof","Vendor"]
  ],
  columns:
  [
     "entityid"
  ]
});

The same can be achieved in SuiteQL using this pattern:

SELECT
  c.id,
  c.entityid
FROM
  customer c
  LEFT JOIN vendor v ON c.id = v.id
WHERE
  v.id IS NULL
ORDER BY
  c.entityid;

How to Remove an Other Relationship

Removing an Other Relationship is simple but unintuitive. You remove it by deleting the record from the entity-type-specific view. For example, if you want to remove the vendor relationship, navigate to the vendor view of the entity and delete it. NetSuite understands that this should break the relationship, not delete the underlying record. When all relationships have been removed in this fashion, a deletion attempt on the entity triggers an actual delete operation, thus; be careful. This pattern also works via SuiteScript. Refer to this article for more information.

Does The Other Relationships Feature Work in Multi-Subsidiary Environments?

To some extent. With the multi-subsidiary features enabled in an account, entities with Other Relationships can span subsidiaries, provided the target entity types support multiple subsidiaries. In testing using an entity acting as both a vendor and a customer, we successfully added multiple subsidiaries to both the vendor and the customer. Even a different set of subsidiaries, or divergent primary subsidiaries, is allowed, as illustrated below.

Comparison of multi-subsidiary settings on the vendor and customer views of a NetSuite entity with Other Relationships

However, on a different entity configured to act as a vendor, customer, and partner, we were unable to select multiple subsidiaries on the vendor or customer. Conversely, the Partner Other Relationships option was unavailable on vendors and customers that already had multiple subsidiaries defined. This is reasonable because Partner records do not support multiple subsidiaries; therefore, NetSuite enforces the least common denominator in such cases.

From Technical Complexity to Practical Clarity

Other Relationships are one of those NetSuite capabilities that look simple in the interface but demand precision once you try to operationalize them. The challenge is not whether the feature works; it does. The challenge is understanding which implementation path fits the actual state of the data.

If the target relationship does not yet exist and you need a quick one-time utility, the URL pattern can be a practical answer. If the relationship needs to be created automatically going forward, record.transform is the cleaner approach for supported record types. If both entity flavors already exist, the right answer is not to force another transform but to intentionally merge them through the deduplication task. Each path solves a different problem, and much of the confusion comes from treating them as interchangeable.

Clarity is the real advantage here. Once the problem is framed correctly, the path forward becomes much easier to see. But that clarity rarely comes from documentation alone; it comes from hands-on testing, paying attention to edge cases, and working through the nuances of how NetSuite actually behaves in different record states and account configurations. That is where ingenuity matters. The best solution is not always the most obvious or the most commonly repeated one; it is the one that has been thoughtfully validated and matched to the situation. With that combination of clarity, testing, and technical creativity, the implementation becomes more reliable and the resulting automation becomes easier to trust, support, and extend.

At Prolecto, this is the kind of applied technical work we enjoy sharing. We believe practical patterns, working examples, and hard-earned implementation details help the NetSuite community make better decisions and avoid unproductive trial and error. In an increasingly AI-augmented world, that kind of grounded guidance also improves the odds that both developers and AI agents produce code that actually works.

If you found this article relevant, feel free to sign up for notifications to new articles as we post them. If you are ready to automate NetSuite Other Relationships with the right technical judgment and implementation approach, let’s have a conversation.

Chidi Okwudire LinkedIn

Chidi Okwudire

Chidi Okwudire is a leading technology expert at Prolecto, specializing in ERP solutions and business intelligence.

BiographyYouTubeLinkedInX (Twitter)

2 thoughts on “NetSuite Other Relationships: 3 Working Approaches for Bulk and Automated Workflows

  1. Chidi & Marty thank you for sharing this. Very valuable research findings. I would also add a use case to change the primary subsidiary you can use the merge process to merge the internalID of the wrong primary Subsidary into the InternalID of the correct surviving primary Subsidary effectively changing the primary subsidiary which is otherwise locked. This becomes important in certain use cases like the native Cash Application only works on the primary subsidiary (which is a stupid limitation!)

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *