user_123 → order ord_998) points at a
relationship type that defines its role, the object types involved, and
metadata like cardinality. Think of it as the schema for your edges.
Creating a relationship requires a relationshipTypeId, so registering
the type — or finding an existing one with GET /relationship-types — is
a prerequisite for linking over the API. Registering also lets you
attach cardinality, description, and bidirectional so your graph is
self-describing and queryable in Segments.
When you register a type, you reference custom object types by
name (
order, line_item). When you create a relationship, you
reference the type by its relationshipTypeId (returned here) — so
register or list your types first. See the FAQ below.What you need before you register
Registration validates against your existing catalog, so have these ready first — in this order:An organization API key
Sent as
Authorization: Bearer boom_org_…. The organization is
derived from the key. See Authentication.The custom object type(s), already created
Both endpoints reference object types by name, and those types
must already exist for your org. An unknown name returns For
404 with
fuzzy suggestions. Confirm with:person_to_co you need one type; for co_to_co you need both the
parent and the child type.Field catalog
Required vs. optional fields perkind. role, cardinality,
description, and bidirectional are common to both.
kind: "person_to_co"
| Field | Required | Type | Notes |
|---|---|---|---|
kind | ✅ | "person_to_co" | Discriminator. |
role | ✅ | string (1–255) | Label for the link, e.g. placed, returned. |
customObjectType | ✅ | string (1–255) | Name of an existing custom object type. |
cardinality | — | enum | One of the cardinality values. |
description | — | string (1–1000) | Human-readable explanation. |
bidirectional | — | boolean | Defaults to false. |
kind: "co_to_co"
| Field | Required | Type | Notes |
|---|---|---|---|
kind | ✅ | "co_to_co" | Discriminator. |
role | ✅ | string (1–255) | Label for the link, e.g. contains. |
parentCustomObjectType | ✅ | string (1–255) | Name of an existing type (parent side). |
childCustomObjectType | ✅ | string (1–255) | Name of an existing type (child side). |
cardinality | — | enum | One of the cardinality values. |
description | — | string (1–1000) | Human-readable explanation. |
bidirectional | — | boolean | Defaults to false. |
Cardinality catalog
cardinality is optional but recommended. For person_to_co, read it as
person→object; for co_to_co, read it as parent→child.
| Value | Meaning | Example (person_to_co) |
|---|---|---|
ONE_TO_ONE | One on each side. | A person has exactly one profile. |
ONE_TO_MANY | One subject, many objects. | A person placed many orders. |
MANY_TO_ONE | Many subjects, one object. | Many people belong to one household. |
MANY_TO_MANY | Many on both sides. | People favorited many products. |
400.
Register a type
created (false when
the type already existed and was refined in place):
List your types
Recommended order of operations
Create custom object types
POST /custom-objects/types (or via your dashboard / data sync). The
public API never auto-creates object types.Register relationship types
POST /relationship-types with cardinality + description. Keep the
relationshipTypeId from the response — you’ll need it to create
relationships.FAQ
Do I send the relationshipTypeId when creating a relationship?
Yes — it’s required. POST /relationships takes the
relationshipTypeId, which fixes the link’s role and which custom
object type it targets, so you don’t pass those separately. Get the id
from the response of POST /relationship-types or from
GET /relationship-types.
What happens if I skip registration?
You can’t —POST /relationships needs a relationshipTypeId, and the
only way to get one is to register a type (or list a type that already
exists from a prior data sync). So registering is a prerequisite for
linking over the API.
Can I change a type’s cardinality later?
Yes — re-POST the same type with the new value. It’s an upsert and only
the fields you send are updated.