This guide explains how departmental systems (CRMs, workflow apps) and downstream consumers (analytics, client processing) integrate with Deal Engine deal programs.
Deal programs are independent services (one per deal type family) but expose a standard interface so callers don’t learn custom APIs per domain.
Key concepts
- Deal type: e.g.,
touring_calcs_v1,endorsement_v1,film_backend_v1 - Model version: immutable version of a deal type definition (schema + clause structure + templates + computation catalog)
- Draft: ephemeral workspace for interactive data entry + what-if (not persisted as a deal)
- Deal: persisted record with immutable revisions and snapshots
- Snapshot: immutable computed state used for deltas and CP integration
- Obligations: the finance-facing line items derived from the deal (what CP consumes)
Service discovery (no facade)
Callers first locate the correct deal program base URL via the Model Registry:
GET {registry}/deal-types/{dealType}- Response includes:
serviceBaseUrl- active model version (and optional canary rules)
Call the deal program at serviceBaseUrl using the standard endpoints below.
Authentication and authorization
- AuthN: Entra ID JWTs (validated by gateway / services).
- Gateway: Azure API Management (APIM) is the default entrypoint.
- AuthZ: AWS Verified Permissions using Cedar policy language.
- AuthZ may be enforced at APIM and/or inside services (background jobs are always service-side).
- Deny responses should include an
authzDecisionIdfor audit correlation.
Clients should:
- send the user bearer token as usual
- propagate correlation headers (see Observability)
Observability headers
Clients should set / propagate:
x-correlation-id(request correlation)x-request-id(if you already use one)
Services emit traces/metrics/logs to Datadog.
Standard endpoints (high level)
Model discovery
GET /modelsGET /models/{dealType}/versionsGET /models/{dealType}/versions/{version}GET /models/{dealType}/versions/{version}/input-schemaGET /models/{dealType}/versions/{version}/ui-schema(optional)GET /models/{dealType}/versions/{version}/workflowGET /models/{dealType}/versions/{version}/calculations
Drafts (interactive entry + what-if)
POST /draftsPATCH /drafts/{draftId}POST /drafts/{draftId}/validatePOST /drafts/{draftId}/computePOST /drafts/{draftId}/commit
Deals
POST /dealsGET /deals/{dealId}PATCH /deals/{dealId}(creates a new revision; optimistic locking)GET /deals/{dealId}/revisionsGET /deals/{dealId}/snapshotsGET /snapshots/{snapshotId}/explain(optional)
CP / obligations
POST /deals/{dealId}/processing/startGET /deals/{dealId}/obligations?asOf=YYYY-MM-DDGET /deals/{dealId}/obligations/delta?fromSnapshot=...&toSnapshot=...POST /deals/{dealId}/payments/ackPOST /deals/{dealId}/invoices/ack(optional)
Workflow state (deal-level, standardized per deal type)
Each deal type defines a strict enum field workflowState (shared across all consuming apps for that deal type).
- Fetch allowed states and canonical mapping:
GET /models/{dealType}/versions/{version}/workflow
- Render a picker constrained to that enum.
- Send the selected value in your draft/deal payload as
workflowState.
Input schema usage
- Use
GET /.../input-schemato render data-entry forms or validate client-side. - Schemas may reference library components in authoring, but deal programs serve a bundled schema appropriate for validation/rendering.
Calculations catalog
GET /.../calculations returns the list of metrics/outputs for the model version:
- key
- type (money/number/int/bool/object/string)
- dependency hints (optional)
Important:
- This is a catalog for UX and documentation.
- The model does not embed an executable expression language.
Draft flow (recommended for CRMs)
Drafts are the primary workflow for interactive entry.
1) Create a draft
POST /drafts
Content-Type: application/json
{ "dealType": "touring_calcs_v1", "modelVersion": "1.0.0" }2) Patch as the user types
PATCH /drafts/{draftId}
Content-Type: application/json
{ "terms": { "artistPct": 0.9 } }3) Validate (lightweight)
POST /drafts/{draftId}/validate4) Compute what-if (throttle/debounce)
POST /drafts/{draftId}/compute
Content-Type: application/json
{ "asOf": "2026-01-15" }5) Commit (creates deal + revision + snapshot)
POST /drafts/{draftId}/commitDeal update flow (optimistic locking)
Deal updates always create a new immutable revision.
- Read the deal:
GET /deals/{dealId}- Update with
If-Match(ETag from GET response):
PATCH /deals/{dealId}
If-Match: "<etag-from-get>"
Content-Type: application/json
{ "workflowState": "HOLD" }Error envelope (recommended)
{
"type": "https://mdm.unitedtalent.com/api/errors/400-bad-request",
"title": "Bad Request",
"status": 400,
"detail": "workflowState must be one of: DRAFT, OFFER_OUT, ...",
"correlationId": "..."
}Performance expectations (interactive UX)
PATCH /drafts/{id}and/validateshould be fast enough for typing workflows.computecan be throttled (e.g., run every 300–700ms).- Avoid calling
computeon every keystroke; call on meaningful checkpoints.
Notes for Client Processing
- CP should call
/processing/startto pin a baseline snapshot. - CP should use obligation deltas classified as amendment vs correction (if enabled by the program).
- CP acknowledgements (
payments/ack,invoices/ack) must be idempotent and auditable.
Last updated: 2026-01-26