---
title: "Contracting &amp; Hierarchies API Overview"
description: "Before a producer can sell a carrier's product, they have to be contracted for it — approved to sell that product, at agreed commission terms, in specific states. Keeping track of who is contracted for what, and at what rate, is the work this API automates."
url: "https://developer.agentsync.io/contracting-api-overview"
image: "https://developer.agentsync.io/_og/d/c_Ocean.takumi,title_~Q29udHJhY3RpbmcgJiBIaWVyYXJjaGllcyBBUEkgT3ZlcnZpZXc,description_~QmVmb3JlIGEgcHJvZHVjZXIgY2FuIHNlbGwgYSBjYXJyaWVyJ3MgcHJvZHVjdCwgdGhleSBoYXZlIHRvIGJlIGNvbnRyYWN0ZWQgZm9yIGl0IOKAlCBhcHByb3ZlZCB0byBzZWxsIHRoYXQgcHJvZHVjdCwgYXQgYWdyZWVkIGNvbW1pc3Npb24gdGVybXMsIGluIHNwZWNpZmljIHN0YXRlcy4gS2VlcGluZyB0cmFjayBvZiB3aG8gaXMgY29udHJhY3RlZCBmb3Igd2hhdCwgYW5kIGF0IHdoYXQgcmF0ZSwgaXMgdGhlIHdvcmsgdGhpcyBBUEkgYXV0b21hdGVzLg,props_eyJ0aGVtZSI6eyJtb2RlIjoibGlnaHQiLCJjb2xvcnMiOnsicHJpbWFyeSI6IiMxODdFRkYifX19,p_Ii9jb250cmFjdGluZy1hcGktb3ZlcnZpZXci,s_n62GJXrLKzfzfupF.png"
---

# Contracting & Hierarchies API Overview

Before a producer can sell a carrier's product, they have to be contracted for it — approved to sell that product, at agreed commission terms, in specific states. Keeping track of who is contracted for what, and at what rate, is the work this API automates.

Those relationships also form a chain. A producer contracts with an agency, the agency sits below an IMO (Independent Marketing Organization), and the IMO connects to the carrier. Every commission payout, every "ready to sell" check, and every compliance review depends on knowing that chain accurately.

**What you can get:**

-   **Producers** — the individuals and firms contracted in your organization
-   **Contracts and contract assignments** — who is contracted to sell which product, and the status of each
-   **Assignment changes** — a dated record of every amendment, for reconciliation and audit
-   **Carriers, products, and commission levels** — your contracting catalog and compensation structure
-   **Your distribution hierarchy** — every position, with its upline, commission level, states, and status — see [Hierarchy Nodes](#hierarchy-nodes)
-   **The hierarchy as it looked on any past date** — for answering "who was this producer's upline when this commission was earned?"

## [Common Use Cases](#common-use-cases)

**Commissions** — determine the upline chain at transaction time by querying the hierarchy with `as_of` set to the transaction date and walking the upline links. Commission level names and values are inlined on each node, so no second call is needed. Detect changes in real time via `hierarchy.producer.changed`.

**Reconciliation and audit** — pull the node list as of a reconciliation date and diff against your local records. Compare two `as_of` snapshots to identify what changed in a window; there is no date-range filter.

**Carriers** — synchronize your product catalog so assignments always reflect current offerings, and track amendments over time with `updated_since` on assignment changes.

**Agencies and MGAs** — read your account configuration (assigned carriers, products, and commission levels) in three calls, then keep downstream systems current with `updated_since` polling plus webhook events.

**Technology partners** — integrate contracting data into agency management systems or producer portals, and build automated compliance checkpoints on assignment status.

## [How It Works](#how-it-works)

The customer-facing API is versioned under `/v2` and is **read-only** — every endpoint is a `GET`. Contracting records are created and maintained in the AgentSync application; your integration consumes them.

Hierarchies are not a separate system layered on top. A hierarchy position **is** a contract assignment, and the tree is formed by the upline links between assignments. That is why the two share one base URL, one set of credentials, one scope model, and one set of response conventions — and why you need carrier, product, and contract assignment data before hierarchy data means anything.

Responses are purpose-built for integrations:

-   **Inlined names** — reference data appears as an `...Id` plus a `...Name` companion (`assignmentStatusId` / `assignmentStatusName`), so there are no lookup round trips.
-   **Incremental sync** — `updated_since` (RFC3339 UTC) returns only records modified at or after that instant. Supported on producers, contracts, contract assignments, assignment changes, assigned carriers, assigned products, and assigned commission levels.
-   **Field conventions** — JSON fields are `lowerCamelCase`; query parameters are `lower_snake_case`. Timestamps end in `At` (RFC3339 UTC); dates end in `On` (`yyyy-MM-dd`).
-   **Account scoping** — a resource that doesn't exist or belongs to another customer returns `404`, never `403`.

Reads require a `contracting.*` scope; see [Authentication](https://developer.agentsync.io/api-authentication) for the scope-to-endpoint mapping, [Base URLs](https://developer.agentsync.io/api-base-urls), and [Pagination](https://developer.agentsync.io/api-pagination) for the token-pagination contract.

### [Hierarchy Nodes](#hierarchy-nodes)

`GET /v2/organizations/{organizationId}/hierarchies` returns your distribution hierarchy as a token-paginated **flat list of nodes**. Each node is one position, keyed by `contractAssignmentId` — the same key the `hierarchy.producer.*` webhook events use, so you can update a stored tree directly from an event.

Four fields carry behavior worth knowing before you build against them:

| Field                      | Why it matters                                                                   |
| :------------------------- | :------------------------------------------------------------------------------- |
| contractAssignmentId       | The node's key. Stable across amendments.                                        |
| uplineContractAssignmentId | The parent's key, or null for root nodes. This is the edge that forms the tree.  |
| type, personId, firmId     | type is AGENT or FIRM and determines which identifier is populated. Both are Identity API identifiers and resolve directly. |
| active                     | Computed over the tree — a node is inactive when its own status is inactive or any node above it is. |

A producer is a single entity discriminated by `type`, not two records — an individual is never stored as both a person and a firm. Whichever identifier does not apply is `null`.

> **Detecting firms: test `firmId` for presence, not `personId` for null.** These fields behave differently across surfaces. On this REST resource a `FIRM` node has `personId: null`. In the `hierarchy.producer.*` [webhook events](https://developer.agentsync.io/contracting-api-webhooks), `personId` is **always** populated, with `firmId` alongside it for firms. Logic branching on `personId == null` works against REST, then silently classifies every firm as an individual when pointed at the event stream. Checking `firmId` for presence is correct in both.

**Reconstructing the tree:** identify root nodes (`uplineContractAssignmentId == null`), group the rest by `uplineContractAssignmentId`, then attach children to their parent keyed on `contractAssignmentId`. Fetch every page first — a child can appear on a later page than its parent.

**Point-in-time snapshots:** pass `as_of=yyyy-MM-dd` to get the hierarchy as it existed on that date. This is the primary mechanism for commissions reconciliation; omit it for current state, and always supply an explicit `as_of` when querying for historical purposes.

**Not yet available on a node:** carrier context, partnership fields, and commission split percentages. If your integration needs these, contact [support@agentsync.io](mailto:support@agentsync.io) so we can factor it into prioritization.

### [Files and Versioning](#files-and-versioning)

Contract packets carry implicit versioning — an initial version and a counter-signed version, surfaced as distinct states.

Files uploaded through the onboarding upload component have no explicit version control. They are versioned at the storage layer, but that history is not exposed: there is no version list and no diff. Webhook events fire when a new file is loaded, so you can detect _that_ a file changed even though you cannot retrieve its history.

### [Webhook Events](#webhook-events)

The API publishes events for contract, assignment, assignment-change, packet, producer-status, responsible-party, and hierarchy changes. Hierarchy lifecycle events are pushed alongside the contracting ones:

| Event                                      | When it fires                                                                    |
| :----------------------------------------- | :------------------------------------------------------------------------------- |
| hierarchy.producer.added                   | A producer is newly placed under an upline                                       |
| hierarchy.producer.changed                 | A position changes — upline and/or commission level. Includes a changedFields array. |
| hierarchy.producer.relationship.terminated | A hierarchy relationship ends — its assignment enters a terminal status          |

See [Contracting API Webhook Events](https://developer.agentsync.io/contracting-api-webhooks) for the full catalog with payload schemas, and the [Webhooks Quick Start Guide](https://developer.agentsync.io/webhooks-quick-start-guide) to register an endpoint.

## [Getting Started](#getting-started)

**Start here:** the [Contracting & Hierarchies API Quick Start Guide](https://developer.agentsync.io/contracting-api-quick-start-guide) walks through authentication, reading your account configuration, producers, assignments and hierarchy, reconstructing the tree, point-in-time snapshots, resolving contact details from Identity, and incremental sync — with curl and Python examples throughout.

For every endpoint, request/response schema, and field constraint, see the interactive [API Reference](https://developer.agentsync.io/apis).