Skip to main content
A relationship type is the shape of a link, not a link itself. Every relationship (e.g. person 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:
1

An organization API key

Sent as Authorization: Bearer boom_org_…. The organization is derived from the key. See Authentication.
2

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 404 with fuzzy suggestions. Confirm with:
curl "$BASE/custom-objects/types" -H "Authorization: Bearer $BOOM_KEY"
For person_to_co you need one type; for co_to_co you need both the parent and the child type.
3

A role and (recommended) the metadata

Decide the role label and, ideally, the cardinality and a short description. These are the fields documented in the catalog below.

Field catalog

Required vs. optional fields per kind. role, cardinality, description, and bidirectional are common to both.

kind: "person_to_co"

FieldRequiredTypeNotes
kind"person_to_co"Discriminator.
rolestring (1–255)Label for the link, e.g. placed, returned.
customObjectTypestring (1–255)Name of an existing custom object type.
cardinalityenumOne of the cardinality values.
descriptionstring (1–1000)Human-readable explanation.
bidirectionalbooleanDefaults to false.

kind: "co_to_co"

FieldRequiredTypeNotes
kind"co_to_co"Discriminator.
rolestring (1–255)Label for the link, e.g. contains.
parentCustomObjectTypestring (1–255)Name of an existing type (parent side).
childCustomObjectTypestring (1–255)Name of an existing type (child side).
cardinalityenumOne of the cardinality values.
descriptionstring (1–1000)Human-readable explanation.
bidirectionalbooleanDefaults to false.
Registering a co_to_co type is supported, but creating a co_to_co relationship is not yet available over the public API — only person↔object links can be created today. Use this to pre-define your schema; object↔object linking will follow.

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.
ValueMeaningExample (person_to_co)
ONE_TO_ONEOne on each side.A person has exactly one profile.
ONE_TO_MANYOne subject, many objects.A person placed many orders.
MANY_TO_ONEMany subjects, one object.Many people belong to one household.
MANY_TO_MANYMany on both sides.People favorited many products.
Any other value is rejected with 400.

Register a type

curl -X POST "$BASE/relationship-types" \
  -H "Authorization: Bearer $BOOM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "person_to_co",
    "role": "placed",
    "customObjectType": "order",
    "cardinality": "ONE_TO_MANY",
    "description": "A person who placed an order"
  }'
The response echoes the resolved type, including created (false when the type already existed and was refined in place):
{
  "kind": "person_to_co",
  "relationshipTypeId": "rt_2hk9",
  "role": "placed",
  "customObjectType": "order",
  "cardinality": "ONE_TO_MANY",
  "description": "A person who placed an order",
  "bidirectional": false,
  "created": true
}
Registration is an upsert — re-post the same (kind, role, type) to refine metadata. Omitted optional fields are preserved, so you can patch just the description without clearing a previously-set cardinality.

List your types

curl "$BASE/relationship-types" -H "Authorization: Bearer $BOOM_KEY"
{
  "personToCo": [
    { "relationshipTypeId": "rt_2hk9", "role": "placed", "customObjectType": "order", "cardinality": "ONE_TO_MANY", "description": "A person who placed an order", "bidirectional": false }
  ],
  "coToCo": [
    { "relationshipTypeId": "rt_8fa1", "role": "contains", "parentCustomObjectType": "order", "childCustomObjectType": "line_item", "cardinality": "ONE_TO_MANY", "description": null, "bidirectional": false }
  ]
}
1

Create custom object types

POST /custom-objects/types (or via your dashboard / data sync). The public API never auto-creates object types.
2

Register relationship types

POST /relationship-types with cardinality + description. Keep the relationshipTypeId from the response — you’ll need it to create relationships.
3

Upsert people and custom objects

POST /people and POST /custom-objects.
4

Create relationships

POST /relationships, passing the relationshipTypeId from step 2.

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.
// POST /relationships — request
{ "personExternalId": "user_123", "customObjectExternalId": "ord_998",
  "relationshipTypeId": "rt_2hk9" }

// response
{ "created": true, "relationshipTypeId": "rt_2hk9" }

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.