{
  "site": {
    "name": "composerID Docs",
    "nav": [
      {
        "title": "Overview",
        "path": "index.html"
      },
      {
        "title": "API",
        "path": "api/index.html"
      },
      {
        "title": "MCP",
        "path": "mcp/index.html"
      },
      {
        "title": "Schemas",
        "path": "schemas/index.html"
      },
      {
        "title": "Integrations",
        "path": "integrations/index.html"
      },
      {
        "title": "Platforms",
        "path": "platforms/index.html"
      }
    ]
  },
  "schemas": [
    {
      "name": "IntentRecord",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/intent-record.json",
      "description": "Canonical system-of-engagement record keyed by intent_id.",
      "breaking": false
    },
    {
      "name": "DiagnosticsBundle",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/diagnostics-bundle.json",
      "description": "Scored diagnostic evidence produced by Triage.",
      "breaking": false
    },
    {
      "name": "RoutingPayload (Common Workforce Model)",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/routing-payload.json",
      "description": "Channel + destination payload in canonical field names.",
      "breaking": false
    },
    {
      "name": "AdminPayload",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/admin-payload.json",
      "description": "Dates, budgets, cost centers, approvals, and administrative fields.",
      "breaking": false
    },
    {
      "name": "PublishingBundle",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/publishing-bundle.json",
      "description": "Publish receipts, external IDs, idempotency keys, and adapter status.",
      "breaking": false
    },
    {
      "name": "MappingProfile",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/mapping-profile.json",
      "description": "Field translation templates from canonical intent/workforce models to platform-specific API dialects.",
      "breaking": false
    },
    {
      "name": "LinkedDestination",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/linked-destination.json",
      "description": "Capability + requirements metadata for a connected tenant.",
      "breaking": false
    },
    {
      "name": "TimelineEvent",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/timeline-event.json",
      "description": "Immutable append-only event stream for auditability.",
      "breaking": false
    },
    {
      "name": "WebhookEvent",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/webhook-event.json",
      "description": "Back-sync event envelope.",
      "breaking": false
    },
    {
      "name": "PassthroughRequest",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/passthrough-request.json",
      "description": "Raw platform call anchored to intent_id for escape-hatch fields/endpoints.",
      "breaking": false
    },
    {
      "name": "ReconciliationReport",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/reconciliation-report.json",
      "description": "Drift detection report when SoR diverges from Intent.",
      "breaking": false
    },
    {
      "name": "EnrichmentRequest",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/enrichment-request.json",
      "description": "Request for missing platform-required fields emitted back to Triage.",
      "breaking": false
    },
    {
      "name": "ComplianceFile (JSON-LD)",
      "version": "1.0.0",
      "schema_url": "https://composer.id/schemas/defence-file.jsonld",
      "description": "Machine-readable evidence pack linked from the intent and the records published from it.",
      "breaking": false
    }
  ],
  "api": {
    "base_url": "https://api.composer.id",
    "endpoints": [
      {
        "method": "POST",
        "path": "/oauth/token",
        "summary": "Exchange client credentials for a short-lived, scoped bearer token.",
        "request": "TokenRequest",
        "response": "TokenResponse"
      },
      {
        "method": "POST",
        "path": "/intent",
        "summary": "Create an intent record (returns intent_id).",
        "request": "IntentCreateRequest",
        "response": "IntentRecord"
      },
      {
        "method": "PATCH",
        "path": "/intent/{intent_id}",
        "summary": "Patch diagnostics/routing/admin fields.",
        "request": "IntentPatchRequest",
        "response": "IntentRecord"
      },
      {
        "method": "POST",
        "path": "/plan",
        "summary": "Generate destination plan from Channel Map + intent.",
        "request": "PlanGenerateRequest",
        "response": "PlanGenerateResponse"
      },
      {
        "method": "POST",
        "path": "/preflight",
        "summary": "Validate intent against platform requirements.",
        "request": "PreflightRequest",
        "response": "PreflightResponse"
      },
      {
        "method": "POST",
        "path": "/publish",
        "summary": "Idempotent publish to target platform via adapter.",
        "request": "PublishRequest",
        "response": "PublishResponse"
      },
      {
        "method": "GET",
        "path": "/intent/{intent_id}",
        "summary": "Fetch the canonical intent record.",
        "request": "none",
        "response": "IntentRecord"
      },
      {
        "method": "GET",
        "path": "/intent/{intent_id}/timeline",
        "summary": "Fetch timeline events for audit.",
        "request": "none",
        "response": "TimelineEvent[]"
      },
      {
        "method": "GET",
        "path": "/platforms",
        "summary": "List platforms and doc availability.",
        "request": "none",
        "response": "PlatformDoc[]"
      },
      {
        "method": "GET",
        "path": "/destinations",
        "summary": "List connected destinations and capabilities.",
        "request": "none",
        "response": "LinkedDestination[]"
      },
      {
        "method": "GET",
        "path": "/destinations/{id}/capabilities",
        "summary": "Capability matrix + required fields per object/op.",
        "request": "none",
        "response": "CapabilitiesResponse"
      },
      {
        "method": "POST",
        "path": "/passthrough",
        "summary": "Send raw JSON to a platform endpoint.",
        "request": "PassthroughRequest",
        "response": "PassthroughResponse"
      },
      {
        "method": "POST",
        "path": "/reconcile",
        "summary": "Detect drift between VMS state and canonical intent.",
        "request": "ReconcileRequest",
        "response": "ReconciliationReport"
      },
      {
        "method": "POST",
        "path": "/enrichment-request",
        "summary": "Emit missing fields back to Triage/Intake.",
        "request": "EnrichmentRequest",
        "response": "EnrichmentAck"
      }
    ],
    "webhooks": [
      {
        "event": "vms.requisition.updated",
        "payload_schema": "WebhookEvent",
        "description": "A requisition changed in the destination system."
      },
      {
        "event": "vms.assignment.updated",
        "payload_schema": "WebhookEvent",
        "description": "An assignment changed."
      },
      {
        "event": "vms.timesheet.updated",
        "payload_schema": "WebhookEvent",
        "description": "Timesheet changed."
      },
      {
        "event": "vms.connection.revoked",
        "payload_schema": "WebhookEvent",
        "description": "Tenant auth revoked."
      }
    ],
    "mcp_tools": [
      {
        "name": "intent_create",
        "input_schema": "IntentCreateRequest",
        "output_schema": "IntentCreateResponse",
        "description": "Initializes a record; returns stable intent_id."
      },
      {
        "name": "intent_patch",
        "input_schema": "IntentPatchRequest",
        "output_schema": "IntentRecord",
        "description": "Updates diagnostics/routing/admin payloads."
      },
      {
        "name": "plan_generate",
        "input_schema": "PlanGenerateRequest",
        "output_schema": "PlanGenerateResponse",
        "description": "Applies Channel Map to identify target destination(s)."
      },
      {
        "name": "mapping_preflight",
        "input_schema": "PreflightRequest",
        "output_schema": "PreflightResponse",
        "description": "Validates intent vs requirements; returns enrichment gaps."
      },
      {
        "name": "adapter_publish",
        "input_schema": "PublishRequest",
        "output_schema": "PublishResponse",
        "description": "Idempotent publish; records external IDs + receipt."
      }
    ]
  },
  "platforms": [
    {
      "platform": "Microsoft Teams",
      "category": "Intake Surfaces",
      "status": "beta",
      "owner": "triage",
      "docs_note": "Bot Framework + Adaptive Cards; Entra ID SSO. Diagnostic questions asked in-chat.",
      "domain": "teams.microsoft.com"
    },
    {
      "platform": "Google Chat",
      "category": "Intake Surfaces",
      "status": "roadmap",
      "owner": "triage",
      "docs_note": "Cards v2 over the Chat API (chat.googleapis.com/v1) with interaction events on an HTTP endpoint. Renderer ready in the reference implementation; transport planned.",
      "domain": "chat.google.com"
    },
    {
      "platform": "Slack",
      "category": "Intake Surfaces",
      "status": "roadmap",
      "owner": "triage",
      "docs_note": "Block Kit + Events API. Renderer ready in the reference implementation; transport planned.",
      "domain": "slack.com"
    },
    {
      "platform": "ServiceNow",
      "category": "Intake Surfaces",
      "status": "roadmap",
      "owner": "triage",
      "docs_note": "Service Portal widget + Employee Center. The diagnostic runs in the requester's existing ServiceNow session; the decision publishes back into the same instance.",
      "domain": "servicenow.com"
    },
    {
      "platform": "Auth0",
      "category": "Systems Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "OAuth 2.0 / OIDC. Management & Authentication APIs.",
      "domain": "auth0.com"
    },
    {
      "platform": "Azure",
      "category": "Systems Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "Azure AD, Resource Manager, Key Vault REST APIs.",
      "domain": "azure.microsoft.com"
    },
    {
      "platform": "AWS",
      "category": "Systems Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "IAM, STS, Secrets Manager APIs.",
      "domain": "aws.amazon.com"
    },
    {
      "platform": "Google Cloud",
      "category": "Systems Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "Cloud IAM, Secret Manager, Cloud Identity APIs.",
      "domain": "cloud.google.com"
    },
    {
      "platform": "Okta",
      "category": "Systems Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "Identity, Users, Groups, OAuth 2.0 REST APIs.",
      "domain": "okta.com"
    },
    {
      "platform": "Domo",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "Data, Dashboard, Dataset REST APIs.",
      "domain": "domo.com"
    },
    {
      "platform": "Tableau",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "REST API, Hyper API, Metadata API.",
      "domain": "tableau.com"
    },
    {
      "platform": "Power BI",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "Datasets, Reports, Dashboards REST APIs.",
      "domain": "powerbi.microsoft.com"
    },
    {
      "platform": "Looker",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "Looker API 4.0. Queries, Dashboards, Looks.",
      "domain": "looker.com"
    },
    {
      "platform": "Qlik",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "REST APIs. Apps, Spaces, Data connections.",
      "domain": "qlik.com"
    },
    {
      "platform": "Snowflake",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "SQL REST API, Snowpipe, External Functions.",
      "domain": "snowflake.com"
    },
    {
      "platform": "Databricks",
      "category": "Reporting Integrations",
      "status": "live",
      "owner": "triage",
      "docs_note": "REST API 2.0. Jobs, Clusters, SQL Warehouses.",
      "domain": "databricks.com"
    },
    {
      "platform": "ChatGPT",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "OpenAI Chat Completions API. GPT-4o, o1.",
      "domain": "openai.com"
    },
    {
      "platform": "Claude",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Anthropic Messages API. Sonnet, Opus, Haiku.",
      "domain": "claude.ai"
    },
    {
      "platform": "Gemini",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Google Generative AI API. Gemini Pro, Flash.",
      "domain": "gemini.google.com"
    },
    {
      "platform": "Bright Data",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Web Scraper, SERP, Dataset APIs.",
      "domain": "brightdata.com"
    },
    {
      "platform": "Moody's",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Orbis, Credit Risk, Company REST APIs.",
      "domain": "moodys.com"
    },
    {
      "platform": "Dun & Bradstreet",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Direct+, D-U-N-S, Compliance REST APIs.",
      "domain": "dnb.com"
    },
    {
      "platform": "Perplexity",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Sonar API. Search-grounded completions.",
      "domain": "perplexity.ai"
    },
    {
      "platform": "ZoomInfo",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Enrich, Search, WebSights REST APIs.",
      "domain": "zoominfo.com"
    },
    {
      "platform": "Crunchbase",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Enterprise API. Organizations, Funding, People.",
      "domain": "crunchbase.com"
    },
    {
      "platform": "LexisNexis",
      "category": "Question Intelligence",
      "status": "live",
      "owner": "triage",
      "docs_note": "Accurint, SmartLinx, Bridger REST APIs.",
      "domain": "lexisnexis.com"
    },
    {
      "platform": "Beeline",
      "status": "mapped",
      "docs_url": "https://developers.beeline.com/",
      "capabilities": {
        "passthrough_available": true,
        "webhooks_available": true,
        "objects": [
          "business_intake_request",
          "intake_form",
          "request",
          "candidate",
          "assignment",
          "worker",
          "statement_of_work",
          "project",
          "task",
          "timesheet",
          "invoice",
          "purchase_order",
          "supplier",
          "attachment"
        ]
      },
      "mapping_profiles": [
        "beeline.business_intake.v1"
      ],
      "category": "Vendor Management & Sourcing",
      "owner": "composerID",
      "docs_note": "Client APIs + Bulk APIs, OAuth 2.0 (24 h tokens, per-API audience). Webhooks for requests, candidates, SOWs, bids, timesheets.",
      "page": "beeline",
      "domain": "beeline.com",
      "channels": [
        "contingent",
        "statement_of_work"
      ]
    },
    {
      "platform": "SAP",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "SAP Business Technology Platform APIs.",
      "page": "sapbtp",
      "domain": "sap.com"
    },
    {
      "platform": "SAP Ariba",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Procurement, Sourcing, Contract REST APIs.",
      "page": "ariba",
      "domain": "ariba.com",
      "channels": [
        "contingent",
        "statement_of_work"
      ]
    },
    {
      "platform": "Globality",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Sourcing, Webhooks, Project APIs.",
      "page": "globality",
      "domain": "globality.com",
      "channels": [
        "statement_of_work",
        "outsourced"
      ]
    },
    {
      "platform": "Coupa",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Requisitions, POs, Invoices, Suppliers REST API.",
      "page": "coupa",
      "domain": "coupa.com",
      "channels": [
        "contingent",
        "statement_of_work"
      ]
    },
    {
      "platform": "Workday",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "HCM, Recruiting, Staffing REST & SOAP APIs.",
      "page": "workday",
      "domain": "workday.com",
      "channels": [
        "contingent",
        "permanent_hire"
      ]
    },
    {
      "platform": "SAP Fieldglass",
      "status": "mapped",
      "docs_url": "https://help.sap.com/doc/a5fdbd31ebe94832aef0eb79066a8087/cloud/en-US/SAPFieldglassRESTAPIIntegrationGeneralReferenceGuide.pdf",
      "capabilities": {
        "passthrough_available": true,
        "webhooks_available": false,
        "objects": [
          {
            "name": "requisition",
            "operations": [
              {
                "op": "FETCH",
                "required_fields": [
                  "external_id"
                ],
                "supported_fields": [
                  "status",
                  "dates",
                  "cost_center",
                  "custom_fields"
                ]
              },
              {
                "op": "CREATE",
                "required_fields": [
                  "start_date",
                  "end_date",
                  "cost_center_id",
                  "job_title"
                ],
                "supported_fields": [
                  "rate",
                  "location",
                  "custom_fields",
                  "attachments"
                ]
              },
              {
                "op": "UPDATE",
                "required_fields": [
                  "external_id"
                ],
                "supported_fields": [
                  "status",
                  "dates",
                  "rate",
                  "custom_fields"
                ]
              },
              {
                "op": "CANCEL",
                "required_fields": [
                  "external_id"
                ],
                "supported_fields": [
                  "status",
                  "reason"
                ]
              }
            ]
          }
        ]
      },
      "mapping_profiles": [
        {
          "name": "fieldglass.requisition.create",
          "target_object": "requisition",
          "mappings": [
            {
              "source_path": "$.routing.start_date",
              "target_field": "WorkStartDate",
              "transform": "date_iso_to_mdy",
              "required_by_platform": true
            },
            {
              "source_path": "$.routing.end_date",
              "target_field": "WorkEndDate",
              "transform": "date_iso_to_mdy",
              "required_by_platform": true
            },
            {
              "source_path": "$.admin.cost_center_id",
              "target_field": "CostCenter",
              "transform": "lookup",
              "required_by_platform": true
            },
            {
              "source_path": "$.intent_id",
              "target_field": "CustomField.IntentID",
              "transform": "none",
              "required_by_platform": false
            },
            {
              "source_path": "$.diagnostics.defence_file.url",
              "target_field": "Attachment",
              "transform": "none",
              "required_by_platform": false
            }
          ]
        }
      ],
      "category": "Vendor Management & Sourcing",
      "owner": "composerID",
      "docs_note": "REST API + OData. 227+ resources.",
      "page": "fieldglass",
      "domain": "fieldglass.com",
      "channels": [
        "contingent",
        "statement_of_work"
      ]
    },
    {
      "platform": "VNDLY",
      "category": "Vendor Management & Sourcing",
      "status": "mapped",
      "owner": "composerID",
      "docs_note": "Workday VNDLY. Customer-provided API docs.",
      "page": "vndly",
      "domain": "vndly.com",
      "channels": [
        "contingent"
      ]
    },
    {
      "platform": "GEP",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "SMART Procurement, S2P REST APIs.",
      "page": "gep",
      "domain": "gep.com",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "Icertis",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Contract, Clause, Obligation REST APIs.",
      "domain": "icertis.com",
      "page": "icertis",
      "channels": [
        "statement_of_work"
      ]
    },
    {
      "platform": "Ironclad",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Workflows, Records, Webhooks REST APIs.",
      "domain": "ironcladapp.com",
      "page": "ironclad",
      "channels": [
        "statement_of_work",
        "outsourced"
      ]
    },
    {
      "platform": "DocuSign",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "eSignature REST API. Envelopes, Templates.",
      "domain": "docusign.com",
      "page": "docusign",
      "channels": [
        "statement_of_work",
        "contingent"
      ]
    },
    {
      "platform": "Adobe Sign",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Agreements, Widgets, Signing REST APIs.",
      "domain": "adobe.com",
      "page": "adobesign",
      "channels": [
        "statement_of_work"
      ]
    },
    {
      "platform": "PandaDoc",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Documents, Templates, Contacts REST API.",
      "domain": "pandadoc.com",
      "page": "pandadoc"
    },
    {
      "platform": "Dropbox Sign",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Signature Request, Template REST APIs.",
      "domain": "hellosign.com",
      "page": "dropboxsign"
    },
    {
      "platform": "Juro",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "REST API v3. Contracts, templates, smartfields, webhooks.",
      "domain": "juro.com",
      "page": "juro"
    },
    {
      "platform": "Zip",
      "category": "Procurement Orchestration",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Requests, Approvals, Intake REST APIs.",
      "page": "zip",
      "domain": "ziphq.com",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "ORO Labs",
      "category": "Procurement Orchestration",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Intake, Routing, Workflow APIs.",
      "page": "oro",
      "domain": "orolabs.ai",
      "channels": [
        "contingent",
        "statement_of_work",
        "outsourced"
      ]
    },
    {
      "platform": "Keelvar",
      "category": "Procurement Orchestration",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Sourcing, Optimization, Events REST APIs.",
      "domain": "keelvar.com"
    },
    {
      "platform": "JAGGAER",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Sourcing, Contracts, Supplier REST APIs.",
      "domain": "jaggaer.com",
      "page": "jaggaer",
      "channels": [
        "statement_of_work",
        "outsourced"
      ]
    },
    {
      "platform": "Agiloft",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "REST/SOAP interface. Knowledgebase tables, contract records, webhooks.",
      "domain": "agiloft.com",
      "page": "agiloft"
    },
    {
      "platform": "Ivalua",
      "category": "Vendor Management & Sourcing",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Procurement, Supplier, Contract REST APIs.",
      "domain": "ivalua.com",
      "page": "ivalua",
      "channels": [
        "statement_of_work",
        "outsourced"
      ]
    },
    {
      "platform": "Tonkean",
      "category": "Procurement Orchestration",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Intake, Orchestration, Module REST APIs.",
      "domain": "tonkean.com"
    },
    {
      "platform": "Basware",
      "category": "Procurement Orchestration",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Purchase, Invoice, Matching REST APIs.",
      "domain": "basware.com"
    },
    {
      "platform": "Fairmarkit",
      "category": "Procurement Orchestration",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Sourcing, Bidding, Supplier REST APIs.",
      "domain": "fairmarkit.com"
    },
    {
      "platform": "SharePoint",
      "category": "File Storage",
      "status": "live",
      "owner": "triage",
      "docs_note": "Graph API. Sites, Drives, Lists.",
      "domain": "sharepoint.com"
    },
    {
      "platform": "OneDrive",
      "category": "File Storage",
      "status": "live",
      "owner": "triage",
      "docs_note": "Graph API. DriveItems, Permissions.",
      "domain": "onedrive.live.com"
    },
    {
      "platform": "Google Drive",
      "category": "File Storage",
      "status": "live",
      "owner": "triage",
      "docs_note": "Drive API v3. Files, Permissions, Changes.",
      "domain": "drive.google.com"
    },
    {
      "platform": "Oracle HCM",
      "category": "HRIS / HCM",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "HCM Cloud REST APIs. Workers, Assignments.",
      "domain": "oracle.com"
    },
    {
      "platform": "SAP SuccessFactors",
      "category": "HRIS / HCM",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "OData APIs. Employee Central, Recruiting.",
      "domain": "sap.com",
      "page": "successfactors",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "UKG",
      "category": "HRIS / HCM",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Pro / Dimensions REST APIs. People, Time.",
      "domain": "ukg.com"
    },
    {
      "platform": "Ceridian Dayforce",
      "category": "HRIS / HCM",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API. Employees, Payroll, HR.",
      "domain": "dayforce.com"
    },
    {
      "platform": "ADP",
      "category": "HRIS / HCM",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Workforce Now, Next Gen APIs. Workers, Pay.",
      "domain": "adp.com",
      "page": "adp",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "BambooHR",
      "category": "HRIS / HCM",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API. Employees, Time Off, Reports.",
      "domain": "bamboohr.com"
    },
    {
      "platform": "Greenhouse",
      "category": "ATS",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Harvest API. Candidates, Jobs, Offers.",
      "domain": "greenhouse.io",
      "page": "greenhouse",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "Lever",
      "category": "ATS",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "REST API. Opportunities, Postings, Users.",
      "domain": "lever.co",
      "page": "lever",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "iCIMS",
      "category": "ATS",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Platform API. People, Jobs, Workflows.",
      "domain": "icims.com",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "SmartRecruiters",
      "category": "ATS",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API. Jobs, Candidates, Offers.",
      "domain": "smartrecruiters.com",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "Bullhorn",
      "category": "ATS",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API. Candidates, Jobs, Placements.",
      "domain": "bullhorn.com",
      "channels": [
        "permanent_hire"
      ]
    },
    {
      "platform": "Avature",
      "category": "ATS",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API. Candidates, Workflows, Forms.",
      "domain": "avature.net"
    },
    {
      "platform": "Eightfold",
      "category": "ATS",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "Talent Intelligence REST APIs.",
      "domain": "eightfold.ai"
    },
    {
      "platform": "Oracle",
      "category": "ERP",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Fusion Cloud REST APIs. Financials, Projects.",
      "domain": "oracle.com",
      "page": "oracle",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "SAP S/4HANA",
      "category": "ERP",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "OData + REST. Purchase Orders, Cost Centers.",
      "domain": "sap.com",
      "page": "s4hana",
      "channels": [
        "statement_of_work",
        "outsourced"
      ]
    },
    {
      "platform": "Microsoft Dynamics 365",
      "category": "ERP",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Dataverse REST API. Finance, Supply Chain.",
      "domain": "dynamics.microsoft.com",
      "page": "dynamics365",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "NetSuite",
      "category": "ERP",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "SuiteTalk REST / SOAP. Records, SuiteQL.",
      "domain": "netsuite.com",
      "page": "netsuite",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "ServiceNow",
      "category": "ITSM / Service Management",
      "status": "live",
      "owner": "triage",
      "docs_note": "Table, CMDB, Flow Designer REST APIs.",
      "domain": "servicenow.com"
    },
    {
      "platform": "ServiceNow",
      "category": "ITSM / Service Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "Import Set API upsert keyed on correlation_id; catalog orders via the Service Catalog API. The decision returns to the instance where it was asked for.",
      "page": "servicenow",
      "domain": "servicenow.com"
    },
    {
      "platform": "Jira Service Management",
      "category": "ITSM / Service Management",
      "status": "live",
      "owner": "triage",
      "docs_note": "REST API v3. Requests, Queues, SLAs.",
      "domain": "atlassian.com"
    },
    {
      "platform": "BMC Helix",
      "category": "ITSM / Service Management",
      "status": "live",
      "owner": "triage",
      "docs_note": "ITSM REST APIs. Incidents, Changes, Assets.",
      "domain": "bmc.com"
    },
    {
      "platform": "Conga CLM",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "REST + Salesforce APIs. Agreements, clauses, documents.",
      "domain": "conga.com",
      "page": "conga"
    },
    {
      "platform": "Evisort (Workday Contract Intelligence)",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "REST API v1. Workflow tickets, documents, metadata.",
      "domain": "evisort.com",
      "page": "evisort"
    },
    {
      "platform": "LinkSquares",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "REST API. Analyze + Finalize agreements, metadata.",
      "domain": "linksquares.com",
      "page": "linksquares"
    },
    {
      "platform": "Sirion",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "B2B REST API. Contracts, draft requests, webhooks.",
      "domain": "sirion.ai",
      "page": "sirion",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "Gatekeeper",
      "category": "Signature & Contract Management",
      "status": "documented",
      "owner": "composerID",
      "docs_note": "JSON:API REST. Vendors, contracts, workflow, webhooks.",
      "domain": "gatekeeperhq.com",
      "page": "gatekeeper",
      "channels": [
        "outsourced"
      ]
    },
    {
      "platform": "ContractPodAi (Leah)",
      "category": "Signature & Contract Management",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API, no public reference. Docs pending.",
      "domain": "contractpodai.com"
    },
    {
      "platform": "Malbek",
      "category": "Signature & Contract Management",
      "status": "roadmap",
      "owner": "composerID",
      "docs_note": "REST API + Konnect connectors, no public reference. Docs pending.",
      "domain": "malbek.io"
    }
  ],
  "platform_docs": [
    {
      "platform": "SAP Fieldglass",
      "key": "fieldglass",
      "docs_confidence": "Public",
      "docs_links": [
        "https://help.sap.com/doc/a5fdbd31ebe94832aef0eb79066a8087/cloud/en-US/SAPFieldglassRESTAPIIntegrationGeneralReferenceGuide.pdf",
        "https://help.sap.com/doc/d63a5197c77a4a35a05e1c338bd7d15d/cloud/en-US/SAPFieldglassApprovalsAPITechnicalSpecifications.pdf"
      ],
      "page": "platforms/providers/fieldglass.html",
      "minimum_viable_mapping": "contingent requisition + timesheet + (optional) SOW",
      "tenant_discovery": "required fields, custom fields, picklists, approval constraints"
    },
    {
      "platform": "Beeline",
      "key": "beeline",
      "docs_confidence": "Public",
      "docs_links": [
        "https://developers.beeline.com/"
      ],
      "page": "platforms/providers/beeline.html",
      "minimum_viable_mapping": "contingent requisition + assignment + timesheet",
      "tenant_discovery": "required fields, custom fields, picklists, approval constraints"
    },
    {
      "platform": "Workday VNDLY",
      "key": "vndly",
      "docs_confidence": "Customer",
      "docs_links": [],
      "page": "platforms/providers/vndly.html",
      "minimum_viable_mapping": "contingent requisition + assignment",
      "tenant_discovery": "required fields, custom fields, picklists, Workday-aligned coding"
    }
  ],
  "provider_docs": [
    {
      "platform": "SAP Fieldglass",
      "key": "fieldglass",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "SAP Fieldglass is a structured, enterprise VMS used to manage large external workforces and SOW services at global scale. composerID turns Triage intent into deterministic Fieldglass records (requisitions, SOW and time objects) handling tenant-specific requirements via preflight and enrichment.",
      "docs_links": [
        {
          "label": "SAP Fieldglass REST API Integration: General Reference (PDF)",
          "url": "https://help.sap.com/doc/a5fdbd31ebe94832aef0eb79066a8087/cloud/en-US/SAPFieldglassRESTAPIIntegrationGeneralReferenceGuide.pdf"
        },
        {
          "label": "SAP Business Accelerator Hub: Fieldglass APIs",
          "url": "https://api.sap.com/"
        },
        {
          "label": "SAP Fieldglass product documentation",
          "url": "https://help.sap.com/docs/SAP_FIELDGLASS"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 (client credentials; SAML and X.509 assertion flows also supported). Credentials and application keys provisioned per tenant/environment.",
        "style": "REST (JSON) + OData; upload/download connectors also accept CSV. 227+ individual REST resources across requisitions, work orders, time sheets and SOW.",
        "base_url": "Tenant + environment specific (provisioned per Fieldglass instance). No single public base URL.",
        "webhooks": "Poll-first. Outbound integration connectors and audit-trail downloads are configured per tenant; no general public webhook bus.",
        "events_posture": "poll",
        "rate_limits": "100 requests/second per API by default; burst to 200 req/s for short durations.",
        "objects": "Job Posting / Requisition, Work Order + revisions, Worker, Time Sheet, Expense, SOW, Invoice, Supplier"
      },
      "mvm": [
        {
          "object": "Requisition (Contingent)",
          "object_note": "Create external worker request",
          "canonical": "role_title, location, start_date, cost_center, worker_type",
          "target": "REST resource (tenant-specific)",
          "required": "Required + tenant required",
          "notes": "Preflight enforces required fields"
        },
        {
          "object": "Statement of Work",
          "object_note": "Create services request / SOW",
          "canonical": "service_category, sow.summary, deliverables[], budget, dates",
          "target": "REST resource (tenant-specific)",
          "required": "Often tenant required",
          "notes": "Attach Compliance File where supported"
        },
        {
          "object": "Timesheet",
          "object_note": "Capture time entries",
          "canonical": "worker_id, period, hours, cost_center",
          "target": "REST resource (tenant-specific)",
          "required": "Required",
          "notes": "Back-sync recommended"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "CustomField.IntentID on the Job Posting / Work Order",
          "required": "Required",
          "notes": "Matches the fieldglass.contingent_requisition.v1 mapping profile; concrete custom-field key confirmed at tenant onboarding"
        }
      ],
      "tenant_note": "Some Fieldglass requirements are program/tenant-defined (custom fields, approval chains, code lists). Even with public PDFs, a tenant connection is needed to confirm required fields and generate a tenant-specific MappingProfile. Legacy SAP landscapes may route via BAPIs/RFCs/IDocs rather than modern REST: confirm the integration path per tenant."
    },
    {
      "platform": "Beeline",
      "key": "beeline",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Beeline is a vendor-neutral VMS commonly chosen for best-of-breed contingent workforce programmes, and the first destination composerID is integrating. Its developer portal publishes machine-readable OpenAPI specifications for a current generation of Client APIs: worker management (request, intake form, candidate, assignment, worker), business intake, project agreement (SOW) reads and approvals, supplier, invoice, time-and-expense, attachment, program and foundational data. Alongside them sit a Webhook Management API and Reporting-as-a-Service for programme-scale reads. The request objects carry a client-supplied externalId, filterable on reads, which is where the Intent ID travels. Beeline's own integration scenarios include exactly composerID's pattern: an intake started in an external system, automated into Beeline, and completed there.",
      "docs_links": [
        {
          "label": "Beeline Developers Portal",
          "url": "https://developers.beeline.com/"
        },
        {
          "label": "API catalog",
          "url": "https://developers.beeline.com/api-catalog"
        },
        {
          "label": "Authentication overview",
          "url": "https://developers.beeline.com/authentication"
        },
        {
          "label": "Integration use cases",
          "url": "https://developers.beeline.com/use-cases"
        },
        {
          "label": "FAQ (rate limits, tokens, webhooks)",
          "url": "https://developers.beeline.com/faq"
        },
        {
          "label": "Reporting as a Service (RaaS)",
          "url": "https://developers.beeline.com/raas"
        },
        {
          "label": "Supplemental Data Service (report-based reads)",
          "url": "https://developers.beeline.com/supplemental-data-service"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 client credentials: POST https://integrations.auth.beeline.com/oauth/token (EU: integrations.eu-auth.beeline.com) with audience set to the target API's base URL. Tokens last 24 hours. Scopes are granted per API product and listed on each spec under Authorizations; a 403 means a missing scope for the site.",
        "style": "REST/JSON. Current-generation Client APIs (worker-management, business-intake, sow, supplier-management, invoice-management, attachment, reference-data, program-data, foundational, bte, webhook-management, each a dated version such as worker-management_2023-07-01) alongside Bulk APIs (client onboarding, worker; async import/export) and RaaS (the supplemental-data_2025-09-01 spec), which exposes any Report Builder report as a JSON endpoint.",
        "base_url": "Three regional gateway pairs. Client APIs at https://client.beeline.com/api and https://client-eu.beeline.com/api (paths under /sites/{clientSiteId}/…), Bulk APIs at https://edge.beeline.com and https://edge-eu.beeline.com (/client-onboarding, /worker), RaaS at https://raas.beeline.com/api and https://raas-eu.beeline.com/api. The site id and credentials are issued at onboarding.",
        "webhooks": "Webhook Management API: subscribe to events for assignments, candidates, suppliers, timesheet submission, SOW approvals, bids and more (~98 event types). Delivery auth is chosen per subscription: HMAC (Beeline stores a base64 secret the subscriber supplies) or OAuth2 against the subscriber's issuer, with a validate-code handshake proving endpoint ownership. Events fire in real time and duplicates can occur; missed events can be retrieved from the event-history endpoint, so recovery does not depend on the push arriving.",
        "events_posture": "push",
        "rate_limits": "Client APIs: 1,000 requests/minute. Client Bulk APIs: 750 PUT/POST and 100 GET requests/minute (portal FAQ).",
        "objects": "Business Intake Request, Intake Form, Request, Candidate, Assignment, Worker, Statement of Work (read/approve), Project, Task, Timesheet, Invoice (read), Supplier, Attachment; Purchase Order via the Bulk gateway only"
      },
      "mvm": [
        {
          "object": "Business Intake Request",
          "object_note": "Create the worker request",
          "canonical": "job_title → jobTitleId · requester → hiringManagerId · location → workLocationId · quantity → quantity · start_date → startDate (all five required by the create schema); end_date → endDate or duration; role_title → requestName",
          "target": "POST /sites/{clientSiteId}/business-intake-requests (business-intake_2025-01-01)",
          "required": "jobTitleId, hiringManagerId, workLocationId, quantity, startDate + tenant required",
          "notes": "The four *Id fields are tenant UUIDs, resolved at preflight from program-data (job titles) and foundational (users, locations, cost centres). Beeline's Request Intake scenario is composerID's publish path"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id → externalId",
          "target": "externalId on the business intake request: client-supplied and filterable on the list endpoint (?externalId=). trackingNumber on the intake-form path",
          "required": "Required",
          "notes": "Both are stock spec fields needing no tenant configuration. Where the programme wants the ID visible as a field on the record, a client-defined field is added via the documented client-defined-values PATCH"
        },
        {
          "object": "Statement of Work",
          "object_note": "Services channel: read, approve, reconcile",
          "canonical": "sow.status, milestones, payments, dates ← reads; approve/reject → approvals",
          "target": "Project Agreement Management API (sow_2025-01-01): GET SOWs/milestones/payments + POST approvals; SOW lifecycle webhooks",
          "required": "Read scope only",
          "notes": "SOWs are created inside Beeline. The API exposes no create endpoint, so this channel is read/approve, not publish. Approval-stage webhooks (pending initial/final approval and more) land milestones on the intent timeline"
        },
        {
          "object": "Worker / Assignment",
          "object_note": "Read back the engagement",
          "canonical": "worker_id, assignment_id, start_date, end_date, rate, status",
          "target": "worker-management_2023-07-01 (#tag/Assignment, #tag/Worker)",
          "required": "Required",
          "notes": "Drives reconciliation: assignment amendments, extensions and terminations show as drift against the Intent Record"
        },
        {
          "object": "Bulk read",
          "object_note": "Reconciliation at programme scale",
          "canonical": "intent_id (filter), status, updated_at",
          "target": "RaaS (supplemental-data_2025-09-01): GET /sites/{clientSiteId}/RunReport/{reportId}, one report per call",
          "required": "Recommended",
          "notes": "Cheaper than per-record polling across a whole programme. The spec authorises it with the same OAuth client credentials (scope run:raas); filtering by Intent ID presumes a report built with the externalId column"
        }
      ],
      "tenant_note": "Everything on this page is verified against Beeline's published OpenAPI specifications (vendored with provenance in the engineering repo, 2026-08-13); it has not yet been exercised against a tenant. That is the sandbox phase, and the exit criteria are published on this page. Beeline programmes carry tenant-specific configuration: picklists and mandatory fields per programme, client-defined field definitions, and webhook subscriptions enabled per site. Scopes are granted per API product at onboarding, so preflight reads the tenant's own required-field set rather than assuming this page's list. Beeline documents no idempotency header, so duplicate safety is built on the externalId filter (find before create). Deep-link URL shapes on this page are illustrative and confirmed per tenant; the IDs they carry come from the APIs above.",
      "data_flow": {
        "intro": "Triage decides and keeps the evidence; Beeline receives a valid request and the identifier that ties it back. This is the complete outbound payload of a contingent publish, taken from the create schema of business-intake_2025-01-01.",
        "sent": [
          {
            "field": "jobTitleId",
            "content": "The job title being requested, as a Beeline UUID",
            "source": "Resolved from the site's own job-title list (program-data)"
          },
          {
            "field": "hiringManagerId",
            "content": "The requesting manager's Beeline user. The only person identifier sent",
            "source": "Resolved from the site's user list (foundational)"
          },
          {
            "field": "workLocationId",
            "content": "Where the work happens, as a Beeline UUID",
            "source": "Resolved from the site's work locations (foundational)"
          },
          {
            "field": "quantity",
            "content": "How many positions",
            "source": "The Triage decision"
          },
          {
            "field": "startDate, endDate or duration",
            "content": "When the engagement starts and ends",
            "source": "The Triage decision"
          },
          {
            "field": "billToCostCenterId, adminCostCenterId, timesheetApproverId",
            "content": "Cost coding and timesheet approver, where the site requires them",
            "source": "Resolved from the site's own lists"
          },
          {
            "field": "requestName, comments",
            "content": "A request title and a one-line provenance note. No diagnostic content",
            "source": "Composed by composerID"
          },
          {
            "field": "externalId",
            "content": "The Intent ID, so the record can be re-found and reconciled",
            "source": "composerID"
          },
          {
            "field": "clientDefinedValues",
            "content": "Only the fields a programme explicitly maps, such as a Source field",
            "source": "Agreed at onboarding"
          }
        ],
        "read_back": [
          "Webhook events as references: the event id, type, time and the Beeline record ids needed for a deep link.",
          "Request and intake status, so the timeline shows where the request has reached.",
          "Assignment dates, rate and status, compared against the Intent Record to detect drift.",
          "SOW approval state, milestones and payments for the services channel.",
          "Timesheet and financial detail, so spend appears against the Intent ID.",
          "Programme-wide reads through a RaaS report keyed on externalId, instead of polling record by record."
        ],
        "never_sent": [
          "The diagnostic conversation: questions asked, answers given, scores, rankings or override events.",
          "The Compliance File, or any link that would expose it without authentication.",
          "Candidate or worker personal data. composerID collects none, and resumes stay in Beeline unless a programme puts them in scope.",
          "Rates, budgets or commercial terms beyond what the programme's mapping explicitly includes.",
          "Credentials, tokens or signing material belonging to any other system."
        ]
      },
      "access": {
        "intro": "Beeline grants scopes per API product, so least privilege is checkable rather than promised. This is the full grant we ask for, and the grant we do not.",
        "requested": [
          {
            "product": "Business Intake (business-intake_2025-01-01)",
            "scopes": "read:business_intake, write:business_intake, read:client_defined, write:client_defined",
            "why": "Publish the request and carry the Intent ID"
          },
          {
            "product": "Worker Management (worker-management_2023-07-01)",
            "scopes": "read:request, read:intake-form, write:intake-form, read:candidate, read:assignment",
            "why": "The intake-form path, and read-back for reconciliation"
          },
          {
            "product": "Webhook Management (webhook-management_2023-07-01)",
            "scopes": "read:webhook_management, write:webhook_management",
            "why": "Subscribe, validate the endpoint, recover missed events"
          },
          {
            "product": "Project Agreement Management (sow_2025-01-01)",
            "scopes": "read:sow, read:project",
            "why": "SOW and milestone read-back. No writes needed"
          },
          {
            "product": "Financial Time & Expense (bte_2023-07-01)",
            "scopes": "read:bte",
            "why": "Timesheet and spend read-back"
          },
          {
            "product": "Supplemental Data (RaaS)",
            "scopes": "run:raas",
            "why": "Programme-scale reconciliation reads"
          }
        ],
        "excluded": "No Foundational Data writes (write:iam, write:org, write:user, write:spend_authority), no supplier or invoice scopes, and no approval-write scopes. Approving time or candidates from a chat surface needs write:bte or write:candidate, which stays a separate and explicit grant rather than something bundled into the publish integration.",
        "proving": [
          "Publish a contingent request end to end with the Intent ID in externalId, re-find it by the list filter, and replay a duplicate publish without creating a second record.",
          "Create a webhook subscription, prove endpoint ownership with the validate handshake, verify delivery authenticity with the agreed method, and recover a deliberately missed event from event history.",
          "Show preflight reading the site's own required fields and picklists, and rejecting an incomplete publish before it reaches Beeline.",
          "Produce a field-level mapping document for the site. Only then does the public coverage status move beyond what the specifications alone support."
        ]
      },
      "scenarios": [
        {
          "name": "Open a job (contingent request)",
          "direction": "publish",
          "flow": "Triage classifies the request as contingent; composerID publishes it through the Business Intake API with the Intent ID in the request's externalId, a stock field that is filterable on reads, so the record is re-findable without storing Beeline internals. The intake appears in Beeline ready for the MSP to progress; the receipt links to the intake record, and the request link attaches when the MSP converts it.",
          "apis": "business-intake_2025-01-01 · client-defined-values (optional visible field)",
          "deep_link": "{tenant_host}/intakes/{intake_id} (illustrative)"
        },
        {
          "name": "Partially complete a form",
          "direction": "round-trip",
          "flow": "Beeline's own Request Intake scenario: an intake starts in an external system and is automated into Beeline, where the MSP reviews the form and creates the corresponding Request. The Intake Form API takes exactly one required field: a client-supplied trackingNumber, which carries the Intent ID. Everything else is free-text pre-fill for what Triage captured, and the deep link lands the MSP or manager on the form to finish the tenant-only fields. Nothing is retyped, and the form is queryable by tracking number.",
          "apis": "worker-management_2023-07-01 (#tag/Request, intake-process/request-forms) · program-data + foundational (valid picklist values)",
          "deep_link": "{tenant_host}/intakes/{intake_id} (illustrative)"
        },
        {
          "name": "Open a bid / track supplier responses",
          "direction": "read",
          "flow": "Once the request is live, bid and candidate-submission events arrive through the Webhook Management API. A candidate submission with its resume lands on the intent timeline as it happens, and the deep link opens the request's candidate list in Beeline.",
          "apis": "webhook-management_2023-07-01 (bid.submitted, candidate.submitted) · worker-management (#tag/Candidate)",
          "deep_link": "{tenant_host}/requests/{request_id}/candidates (illustrative)"
        },
        {
          "name": "Follow an SoW (services channel)",
          "direction": "read",
          "flow": "Statements of Work are created inside Beeline. Its API exposes no SOW create endpoint, and this page does not pretend otherwise. What the API does give the intent timeline: approval-stage webhooks as the SOW moves through its lifecycle, real-time reads of the SOW, its milestones and payments for reconciliation, and approve/reject calls on SOWs and milestone payments from wherever the approver works.",
          "apis": "sow_2025-01-01 (Project Agreement Management: reads + approvals) · webhook-management (SOW events)",
          "deep_link": "{tenant_host}/sows/{sow_id} (illustrative)"
        },
        {
          "name": "Approve time and spend where it happens",
          "direction": "read",
          "flow": "A timesheet submitted in Beeline raises a webhook; composerID retrieves the timesheet and financial detail so spend appears against the Intent ID, and can approve or reject it. Project milestone payments follow the same pattern: a pending event, a read, and an approve/reject call from wherever the approver works.",
          "apis": "bte_2023-07-01 (#tag/Timesheet: read + approve/reject) · sow_2025-01-01 (milestone payments) · webhook-management (timesheet.submittedforapproval)"
        },
        {
          "name": "Programme-scale reconciliation",
          "direction": "read",
          "flow": "Any Report Builder report becomes a JSON endpoint through Reporting-as-a-Service, one report per call, so composerID sweeps a programme for drift with a report keyed on externalId instead of polling record by record. Attachments come back as binary through the Attachment API when the evidence pack needs the source documents.",
          "apis": "RaaS (supplemental-data_2025-09-01, scope run:raas) · attachment_2025-01-01"
        }
      ]
    },
    {
      "platform": "VNDLY",
      "key": "vndly",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "Workday VNDLY is a cloud-native VMS aligned to the Workday suite. composerID treats VNDLY as a destination system of record (publishing Intent Records and maintaining the audit spine) with tenant mapping validated in a customer sandbox because API documentation is customer/partner-scoped.",
      "docs_links": [
        {
          "label": "Workday VNDLY: product site",
          "url": "https://www.vndly.com/"
        }
      ],
      "api": {
        "auth": "Customer/partner-provisioned credentials within the Workday ecosystem. Confirm auth flow (OAuth 2.0 / ISU-style integration user) per tenant.",
        "style": "Customer-scoped APIs; public endpoint documentation not confirmed. Workday-suite alignment drives object and required-field conventions.",
        "base_url": "Provisioned per customer tenant. No public base URL.",
        "webhooks": "Not publicly documented; plan poll-based reconciliation and confirm event options per tenant.",
        "events_posture": "poll",
        "rate_limits": "Not publicly documented; defined per tenant/integration agreement.",
        "objects": "Requisition, Worker, Assignment, Timesheet, Supplier (per Workday-ecosystem conventions)"
      },
      "mvm": [
        {
          "object": "Requisition (Contingent)",
          "object_note": "Create worker request",
          "canonical": "role_title, location, start_date, cost_center, worker_type",
          "target": "Customer API (Workday ecosystem)",
          "required": "Tenant required",
          "notes": "Workday alignment drives required fields"
        },
        {
          "object": "Worker / Assignment",
          "object_note": "Assignment lifecycle",
          "canonical": "worker_id, dates, rate, status",
          "target": "Customer API",
          "required": "Tenant required",
          "notes": "Back-sync into intent timeline"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Custom field on the job posting / work order",
          "required": "Required",
          "notes": "Customer-scoped API: field key agreed with the joint customer at onboarding"
        }
      ],
      "tenant_note": "Workday VNDLY documentation is customer/partner-scoped. composerID starts with minimum viable mapping and relies on tenant discovery (required fields, custom fields, code lists) to generate a working MappingProfile."
    },
    {
      "platform": "SAP Ariba",
      "key": "ariba",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "SAP Ariba is an enterprise source-to-pay and sourcing suite. Contingent services and SOW work are modelled through Sourcing Projects, Requisitions and Contract Workspaces rather than a single VMS object. composerID maps canonical intent onto those objects across Ariba's REST, SOAP and cXML surfaces.",
      "docs_links": [
        {
          "label": "SAP Business Accelerator Hub: Ariba REST APIs",
          "url": "https://api.sap.com/package/SAPAribaOpenAPIs/rest"
        },
        {
          "label": "Making REST API calls with OAuth token + application key",
          "url": "https://help.sap.com/docs/ariba-apis/help-for-sap-ariba-developer-portal/making-of-rest-api-calls-with-oauth-access-token-and-application-key"
        },
        {
          "label": "SAP Ariba SOAP Web Service APIs",
          "url": "https://help.sap.com/docs/strategic-sourcing/soap-web-service-api-integration/what-are-sap-ariba-soap-web-service-apis"
        },
        {
          "label": "SAP Ariba Developer Portal",
          "url": "https://developer.ariba.com/"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 client-credentials PLUS a per-API Application Key. Every call sends apiKey + Authorization: Bearer. Token from https://api.ariba.com/v2/oauth/token. One application per API per realm.",
        "style": "REST (JSON) + SOAP (strategic sourcing) + cXML (transactional documents over Ariba Network)",
        "base_url": "https://openapi.ariba.com/api/{service}/{version}/{env}  e.g. /sourcing-approval/v2/prod",
        "webhooks": "Poll-first. cXML push over Ariba Network; External Approval API for inbound/outbound approvals. No general object-change webhook bus.",
        "events_posture": "poll",
        "rate_limits": "Per app key + per API, multi-window (per sec/min/hour/day). Varies widely by API; raised case-by-case via account exec.",
        "objects": "Sourcing Project, Sourcing Request / Requisition, Purchase Order, Supplier, Contract Workspace (SOW), Invoice (cXML)"
      },
      "mvm": [
        {
          "object": "Requisition (Contingent)",
          "object_note": "Create external worker request",
          "canonical": "role_title, location, start_date, cost_center, worker_type",
          "target": "Operational Requisition / Sourcing Request",
          "required": "Required + tenant required",
          "notes": "Preflight enforces tenant-required fields"
        },
        {
          "object": "Statement of Work",
          "object_note": "Services / SOW engagement",
          "canonical": "service_category, sow.summary, deliverables[], budget, dates",
          "target": "Contract Workspace (SOW type)",
          "required": "Often tenant required",
          "notes": "SOW is modelled as a contract-workspace type"
        },
        {
          "object": "Purchase Order",
          "object_note": "Transact the order",
          "canonical": "po_lines, supplier, amount",
          "target": "cXML PO over Ariba Network",
          "required": "Network-dependent",
          "notes": "Transacted via Ariba Network"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "cXML Extrinsic / custom field on the requisition",
          "required": "Required",
          "notes": "Extrinsics ride existing cXML documents; realm-level app approval governs write access"
        }
      ],
      "tenant_note": "SOW / contingent labour is not a first-class REST object; field-level schemas live in per-API WSDL/OpenAPI specs on the Business Accelerator Hub, several behind Hub login. App keys take ~12h to activate, and apps are promoted from test realm to production."
    },
    {
      "platform": "Coupa",
      "key": "coupa",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Coupa is a Business Spend Management platform with a single clean REST surface. Contingent and services spend (SOW, Coupa Contingent Workforce) sits on top of requisitions, contracts and purchase_orders. composerID publishes canonical intent into those resources.",
      "docs_links": [
        {
          "label": "The Coupa Core API (Compass)",
          "url": "https://compass.coupa.com/en-us/products/product-documentation/integration-technical-documentation/the-coupa-core-api"
        },
        {
          "label": "Coupa Core API: Get Started",
          "url": "https://compass.coupa.com/en-us/products/product-documentation/integration-technical-documentation/the-coupa-core-api/get-started-with-the-api"
        },
        {
          "label": "OAuth 2.0 and OIDC",
          "url": "https://compass.coupa.com/en-us/products/product-documentation/integration-technical-documentation/the-coupa-core-api/oauth-2.0-and-oidc"
        },
        {
          "label": "Exception handling & rate limits",
          "url": "https://compass.coupa.com/en-us/products/product-documentation/integration-technical-documentation/the-coupa-core-api/get-started-with-the-api/exception-handling-and-error-codes"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 / OIDC client-credentials with scopes. Token POST https://{instance}.coupahost.com/oauth2/token. Legacy X-COUPA-API-KEY header is retired.",
        "style": "REST, JSON or XML via Accept header",
        "base_url": "https://{instance}.coupahost.com/api/{resource}  (events at https://{instance}.cso.coupahost.com/api/events)",
        "webhooks": "Poll-first via updated-at filters. Events API (CSO) + configurable webhooks supplement; not comprehensive native webhooks.",
        "events_posture": "mixed",
        "rate_limits": "25 requests/second, burst queue ~20; exponential backoff on 429/503.",
        "objects": "requisitions, purchase_orders, invoices, contracts, suppliers, quote_requests, expenses, budget_lines"
      },
      "mvm": [
        {
          "object": "Requisition (Contingent)",
          "object_note": "Create external worker request",
          "canonical": "role_title, start_date, end_date, cost_center, worker_type",
          "target": "POST /api/requisitions",
          "required": "Required",
          "notes": "CCW / Services modelled on requisitions"
        },
        {
          "object": "Statement of Work",
          "object_note": "Services / SOW engagement",
          "canonical": "service_category, sow.summary, deliverables[], budget, dates",
          "target": "/api/contracts + /api/requisitions",
          "required": "Tenant required",
          "notes": "Verify CCW module resource name per tenant"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "custom-fields on the requisition / order header",
          "required": "Required",
          "notes": "Coupa custom fields are instance-configured and queryable once defined"
        },
        {
          "object": "Purchase Order",
          "object_note": "Read for back-sync",
          "canonical": "po_number, supplier, amount, status",
          "target": "GET /api/purchase_orders",
          "required": "Required",
          "notes": "Used for reconciliation"
        }
      ],
      "tenant_note": "SOW / Contingent Workforce is not a distinct top-level REST resource; confirm the CCW module resource name in your tenant. Each customer has a separate sandbox instance with its own OAuth clients and scopes."
    },
    {
      "platform": "Workday",
      "key": "workday",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Workday is the worker and staffing system of record. composerID contracts contingent workers through the Staffing business-process operations; writes are largely SOAP-only, while reads are available via REST and RaaS.",
      "docs_links": [
        {
          "label": "Workday SOAP API Reference",
          "url": "https://community-content.workday.com/en-us/public/products/platform-and-product-extensions/soap-api-reference.html"
        },
        {
          "label": "Workday Web Services Production Directory (v46.2)",
          "url": "https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html"
        },
        {
          "label": "Contract_Contingent_Worker operation",
          "url": "https://community.workday.com/sites/default/files/file-hosting/productionapi/Staffing/v14/Contract_Contingent_Worker.html"
        },
        {
          "label": "Workday REST Directory",
          "url": "https://community.workday.com/sites/default/files/file-hosting/restapi/"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 (auth-code + ISU client-credentials) for REST; WS-Security or OAuth via an Integration System User (ISU) for SOAP. Access tokens ~1h; non-expiring refresh tokens configurable.",
        "style": "SOAP (Workday Web Services: primary), REST/JSON (partial subset), RaaS (reports-as-a-service)",
        "base_url": "REST https://{host}/ccx/api/{service}/v{n}/{tenant}  |  SOAP https://{host}/ccx/service/{tenant}/{WebService}/v{n}",
        "webhooks": "No native webhooks. Event-driven via the Business Process Framework, EIB outbound, Studio and Extend. RaaS is poll-based.",
        "events_posture": "poll",
        "rate_limits": "Not officially published; practitioner ~10 req/s per tenant, HTTP 429 + Retry-After. Queue + exponential backoff.",
        "objects": "Staffing (Create_Position, Contract_Contingent_Worker, End_Contingent_Worker_Contract), Job Requisition, Position, Worker, Supplier, Purchase Order"
      },
      "mvm": [
        {
          "object": "Contingent worker (contract)",
          "object_note": "Onboard external worker",
          "canonical": "worker, position, start_date, supplier, job_profile",
          "target": "Contract_Contingent_Worker (Staffing SOAP BP)",
          "required": "Required + tenant BP",
          "notes": "Approvals run via the tenant business process"
        },
        {
          "object": "Position (create)",
          "object_note": "Create the headcount",
          "canonical": "role_title, org, location, headcount",
          "target": "Create_Position (Staffing SOAP)",
          "required": "Required",
          "notes": "Precedes contracting"
        },
        {
          "object": "End contract",
          "object_note": "Offboard / liveness",
          "canonical": "worker_id, end_date, reason",
          "target": "End_Contingent_Worker_Contract",
          "required": "Required",
          "notes": "Drives liveness + offboarding"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Integration reference ID / custom object field on the requisition",
          "required": "Required",
          "notes": "Reference IDs or a tenant custom object carry the correlation; confirmed per tenant"
        }
      ],
      "tenant_note": "Pin a WWS version (e.g. v46.1) in every endpoint. Requires an ISU + integration security group + registered API client. Implementation and production tenants use different hosts."
    },
    {
      "platform": "GEP",
      "key": "gep",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "GEP SMART is a unified source-to-pay procurement platform. Reference docs are public, but working credentials and base URLs are provisioned per customer at onboarding. composerID maps intent onto Requisition / RFX / Contract / Order / Invoice resources.",
      "docs_links": [
        {
          "label": "GEP Tech Documentation portal",
          "url": "https://api.gep.com/"
        },
        {
          "label": "GEP SMART REST APIs index",
          "url": "https://api.gep.com/gep-smart/gep-rest-apis"
        },
        {
          "label": "Order (PO) API",
          "url": "https://api.gep.com/gep-smart/gep-rest-apis/transaction-data-apis/order"
        },
        {
          "label": "Invoice API",
          "url": "https://api.gep.com/gep-smart/gep-rest-apis/transaction-data-apis/invoice"
        }
      ],
      "api": {
        "auth": "OAuth 2.0. Client credentials are provisioned by GEP: there is no public self-service signup. 401 on unauthorized.",
        "style": "REST (JSON) + SOAP + Bulk APIs + FTP/SFTP. GEP QUANTUM adds cXML / EDI-X12 / PIDX.",
        "base_url": "api/{Resource}/{Action}  e.g. api/Order/OrderDetails  (fully-qualified host issued per tenant)",
        "webhooks": "None documented. Request/response REST + Bulk + file exchange; status-update endpoints (OrderStatus, InvoiceStatus) for poll / push-status.",
        "events_posture": "poll",
        "rate_limits": "None published; defined per integration agreement. Bulk APIs handle high volume.",
        "objects": "Requisition, RFX (sourcing), Contract, Order (PO), Invoice, Catalog; master data Suppliers / Category / Users"
      },
      "mvm": [
        {
          "object": "Requisition",
          "object_note": "Create the demand",
          "canonical": "role_title, service_category, cost_center, dates",
          "target": "POST api/Requisition/...",
          "required": "Required",
          "notes": "Convention: POST …Details / GET …All / PUT …Status"
        },
        {
          "object": "Sourcing event (RFX)",
          "object_note": "Competitive services",
          "canonical": "service_category, sow.summary, suppliers[]",
          "target": "RFX API",
          "required": "Tenant required",
          "notes": "For competitively sourced services"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Custom attribute / external reference on the document",
          "required": "Required",
          "notes": "Provisioned with GEP at onboarding: no self-service field creation"
        },
        {
          "object": "Order (PO)",
          "object_note": "Transact + back-sync",
          "canonical": "po_lines, supplier, amount",
          "target": "POST api/Order/OrderDetails; GET api/Order/GetPurchaseOrders",
          "required": "Required",
          "notes": "PUT api/Order/OrderStatus for back-sync"
        }
      ],
      "tenant_note": "No open self-service portal: base URL, tenant ID, sandbox and full auth specs are provisioned by GEP during onboarding. Two products: GEP SMART (source-to-pay) and NEXXE (supply chain); GEP QUANTUM is the platform layer."
    },
    {
      "platform": "Globality",
      "key": "globality",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Globality is an AI-guided services-sourcing platform. Its public REST API exposes a fixed domain model (Project to Brief to Provider to Proposal to Award) that composerID reads to track services and SOW sourcing intent end to end.",
      "docs_links": [
        {
          "label": "Globality Developer API",
          "url": "https://www.globality.com/developer-api"
        },
        {
          "label": "Integration overview",
          "url": "https://www.globality.com/integration"
        },
        {
          "label": "OpenAPI spec (spec.json)",
          "url": "https://www.globality.com/wp-content/uploads/2026/06/spec.json"
        },
        {
          "label": "Webhooks overview",
          "url": "https://www.globality.com/product-innovation-journey/webhooks"
        },
        {
          "label": "Webhooks documentation (PDF, v5)",
          "url": "https://www.globality.com/hubfs/Integration%20and%20API%20pages/Globality%20Webhooks%20Documentation%20v5.pdf"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 client-credentials to a Bearer JWT via Auth0 (POST https://globality-prod.auth0.com/oauth/token, audience per environment). Token TTL 24h. Scopes read:project / write:project.",
        "style": "REST (JSON), versioned /v2, OpenAPI / Swagger",
        "base_url": "US https://apis.prod.globality.com  |  EU https://apis.eu.globality.com",
        "webhooks": "Yes: push webhooks, registered in-app per event type. Documented events: Brief Completed, Brief Updated, Proposal Submitted, Proposal Approved, Award Completed (Globality adds event types over time; an earlier v8 of the PDF also listed Project Status Change). Thin payload (event, projectId, providerId where relevant, timestamp): call back to /v2 for detail. Retries at 1/3/6/12/24h, then the endpoint is auto-disabled and you are emailed.",
        "events_posture": "push",
        "rate_limits": "Not publicly documented; confirm per tenant.",
        "objects": "Project, Brief, Provider (supplier), Proposal, Award, Files"
      },
      "mvm": [
        {
          "object": "Project (create)",
          "object_note": "Container for sourcing intent",
          "canonical": "service_category, sow.summary, budget, dates",
          "target": "POST /v2/projects",
          "required": "Required",
          "notes": "Project is the sourcing-intent container"
        },
        {
          "object": "Brief (read)",
          "object_note": "Scoped requirement",
          "canonical": "requirement, budget, timeline, services",
          "target": "GET /v2/projects/{id}",
          "required": "Read",
          "notes": "Auto-created from the intake form"
        },
        {
          "object": "Award (read)",
          "object_note": "Outcome / receipt",
          "canonical": "completion, dates, po_ref",
          "target": "webhook AwardCompleted then GET /v2",
          "required": "Read",
          "notes": "Feeds the publish receipt"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Project external reference (link-only until write support confirmed)",
          "required": "Required",
          "notes": "Read-centric API: composerID records the intent_id ↔ project linkage on its own side"
        }
      ],
      "tenant_note": "Public docs + OpenAPI, but credentials are customer-gated (an admin assigns the in-app Developer role). Region-specific base URLs and Auth0 audience per environment. The API is read-centric: Project create + status update only; there is no public endpoint to push your own supplier lists. Pre-built connectors exist for Ariba, Fieldglass and Coupa."
    },
    {
      "platform": "SAP BTP",
      "key": "sapbtp",
      "category": "Systems Integrations",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "SAP Business Technology Platform is a generic integration platform, not a single API. composerID treats it as a connectivity fabric: fronting backend systems via API Management, resolving targets via Destinations, authenticating with XSUAA, and receiving callbacks via Event Mesh.",
      "docs_links": [
        {
          "label": "SAP BTP platform docs",
          "url": "https://help.sap.com/docs/btp/sap-business-technology-platform"
        },
        {
          "label": "Integration Suite: OData API",
          "url": "https://help.sap.com/docs/integration-suite/sap-integration-suite/odata-api"
        },
        {
          "label": "Destination service REST API",
          "url": "https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/calling-destination-service-rest-api"
        },
        {
          "label": "Event Mesh: messaging protocols",
          "url": "https://help.sap.com/docs/event-mesh/event-mesh/messaging-protocols-and-libraries"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 via XSUAA. A service key yields clientid / clientsecret / url, then {url}/oauth/token with client_credentials.",
        "style": "Mixed: OData V2 (Cloud Integration management), REST/JSON (Destination), REST/OData/SOAP proxies (API Management), AMQP/MQTT/REST (Event Mesh)",
        "base_url": "https://{subaccount}-tmn.{region}.hana.ondemand.com/api/v1/...  (tenant + region specific)",
        "webhooks": "Yes: Event Mesh (AMQP 1.0 / MQTT 3.1.1 / HTTP-REST) supports webhook delivery; Advanced Event Mesh for high-throughput streaming. Push + poll.",
        "events_posture": "push",
        "rate_limits": "No platform-wide figure; API Management is itself the rate-limiter (Quota / Spike Arrest policies you configure). Per service plan.",
        "objects": "Integration iFlows (IntegrationDesigntimeArtifacts / RuntimeArtifacts), API Proxies / Products, Destinations, Event Mesh queues / topics / webhooks"
      },
      "mvm": [
        {
          "object": "Destination (resolve)",
          "object_note": "Find the backend",
          "canonical": "target_system_name",
          "target": "/destination-configuration/v1/destinations/{name}",
          "required": "Required",
          "notes": "Resolves URL + auth at runtime"
        },
        {
          "object": "iFlow (publish)",
          "object_note": "Map + deliver",
          "canonical": "canonical payload",
          "target": "Cloud Integration iFlow endpoint",
          "required": "Tenant build",
          "notes": "Field mapping happens inside the iFlow"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Propagated as a header/property through the integration flow",
          "required": "Required",
          "notes": "BTP is transit, not a system of record: the durable carrier is the target system's field"
        },
        {
          "object": "Event subscription",
          "object_note": "Back-sync",
          "canonical": "topic / queue",
          "target": "Event Mesh webhook",
          "required": "Optional",
          "notes": "Receives backend status callbacks"
        }
      ],
      "tenant_note": "Public docs, account-gated provisioning (global account to subaccount to service instances + keys). Hostnames embed tenant + region. A free / trial tier and the Business Accelerator Hub sandbox are available. For VMS use, front each backend behind API Management + Destinations + Event Mesh."
    },
    {
      "platform": "Zip",
      "key": "zip",
      "category": "Procurement Orchestration",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "Zip is an intake-to-procure orchestration platform: one front door for any purchase request that routes through the right approvals and into the ERP. Its REST API and low-code App Studio let partners read and write Zip's procurement objects, so composerID can hand canonical intent to Zip's intake and let the orchestrated flow carry it through to purchase order: Zip as a complementary orchestration partner, not a destination-of-record.",
      "docs_links": [
        {
          "label": "Zip: Intake-to-Procure",
          "url": "https://zip.com/products/intake-to-procure"
        },
        {
          "label": "Zip App Studio (low-code integrations)",
          "url": "https://zip.com/products/app-studio"
        },
        {
          "label": "Zip integration ecosystem",
          "url": "https://zip.com/capabilities/integration-ecosystem"
        },
        {
          "label": "Zip for Procurement",
          "url": "https://zip.com/solutions/procurement"
        }
      ],
      "api": {
        "auth": "Credential-based: unique keys issued per partner for separate sandbox and production environments. Build and certify against sandbox, then enable in production. No public self-service signup.",
        "style": "REST (JSON request/response, standard HTTP status codes). App Studio adds low-code REST/SOAP endpoint actions, triggers and branching.",
        "base_url": "Provisioned per customer (sandbox + production). No single public base URL.",
        "webhooks": "Event-driven via App Studio triggers + bi-directional sync; integration status and activity logs. Push or poll depending on the configured action.",
        "events_posture": "mixed",
        "rate_limits": "Not publicly documented; defined per partner integration agreement.",
        "objects": "Intake / purchase request, Requisition, Vendor (supplier), Contract, Purchase Order, Invoice"
      },
      "mvm": [
        {
          "object": "Intake request",
          "object_note": "The single front door",
          "canonical": "role_title, service_category, cost_center, dates, amount",
          "target": "Intake / Purchase Request (App Studio action)",
          "required": "Required",
          "notes": "Zip routes it through the right approvals"
        },
        {
          "object": "Vendor",
          "object_note": "Resolve / onboard supplier",
          "canonical": "supplier_name, tax_id, contact",
          "target": "Vendor object",
          "required": "Tenant required",
          "notes": "Vendor onboarding gates the PO"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Custom field on the intake request",
          "required": "Required",
          "notes": "Fields provisioned by Zip per partner; link-only correlation until provisioned"
        },
        {
          "object": "Purchase Order",
          "object_note": "Transact + back-sync",
          "canonical": "po_lines, supplier, amount, status",
          "target": "Purchase Order object",
          "required": "Read",
          "notes": "Read for reconciliation / liveness"
        }
      ],
      "tenant_note": "Zip is configuration-heavy: intake forms, approval chains, custom fields and routing logic are tenant-defined in the workflow builder, and App Studio is the supported low-code path for custom triggers and actions. The API surface is partner-gated: endpoints, credentials and base URLs are provisioned by Zip during onboarding. Note: ziphq.com (now zip.com) is the procurement platform, which is unrelated to the Zip Co buy-now-pay-later product at zip.co."
    },
    {
      "platform": "ORO Labs",
      "key": "oro",
      "category": "Procurement Orchestration",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "ORO Labs is an AI procurement-orchestration platform built on an embedded iPaaS. Rather than one public REST object model, ORO federates 200+ semantically rich integrations across ERP, procure-to-pay, contract and risk systems. composerID maps canonical intent onto ORO's intake-request and workflow objects so services and contingent demand enter the orchestrated source-to-pay flow.",
      "docs_links": [
        {
          "label": "ORO Labs: Integrations",
          "url": "https://www.orolabs.ai/platform/integrations"
        },
        {
          "label": "ORO Labs: Platform overview",
          "url": "https://www.orolabs.ai/platform/overview"
        },
        {
          "label": "ORO Labs: Intake management",
          "url": "https://www.orolabs.ai/solutions/intake-management"
        },
        {
          "label": "ORO Labs: Agentic AI",
          "url": "https://www.orolabs.ai/platform/agentic-ai"
        }
      ],
      "api": {
        "auth": "SSO + role-based access control with encryption; SOC 1, SOC 2 and ISO 42001 (responsible AI) certified. API credentials are provisioned per customer: no public self-service developer portal.",
        "style": "Embedded iPaaS connectors (semantically rich: the platform understands suppliers, line items and contracts) rather than a single public REST surface; workflow triggers + real-time data sync.",
        "base_url": "Per-customer tenant, provisioned at onboarding. No public base URL.",
        "webhooks": "Real-time data sharing and activity triggering across systems via the embedded iPaaS; event-driven workflow triggers. Delivery specs provisioned per integration.",
        "events_posture": "mixed",
        "rate_limits": "Not publicly documented; defined per integration.",
        "objects": "Intake request, Approval, Supplier, Contract, Risk assessment, Purchase Order, Invoice (source-to-pay)"
      },
      "mvm": [
        {
          "object": "Intake request",
          "object_note": "Start the orchestration",
          "canonical": "service_category, sow.summary, budget, dates",
          "target": "Intake request (orchestrated workflow)",
          "required": "Required",
          "notes": "Routes through the configured source-to-pay flow"
        },
        {
          "object": "Supplier",
          "object_note": "Resolve + risk",
          "canonical": "supplier_name, tax_id, risk_flags",
          "target": "Supplier object + risk assessment",
          "required": "Tenant required",
          "notes": "Risk / onboarding gates progression"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Intake workflow field (configured per customer)",
          "required": "Required",
          "notes": "No public API surface: linkage recorded on the composerID side, field write via ORO connector"
        },
        {
          "object": "Contract / PO",
          "object_note": "Back-sync",
          "canonical": "contract_ref, po_lines, amount, status",
          "target": "Contract + PO via iPaaS connector",
          "required": "Read",
          "notes": "Synced from the downstream ERP / P2P system"
        }
      ],
      "tenant_note": "ORO is an orchestration layer, not a transactional system of record: it federates to your ERP / P2P (SAP, Oracle, NetSuite, Coupa, Ariba, JAGGAER, GEP) through its embedded iPaaS. There is no public REST object catalogue; integration is delivered via ORO's connector framework and provisioned per customer. Public API, auth and webhook specifications are not published."
    },
    {
      "platform": "DocuSign",
      "key": "docusign",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "DocuSign eSignature is the execution and evidence layer for a decision. composerID publishes an Intent as a signature Envelope, embeds the Intent ID as an envelope custom field, and tracks completion through DocuSign Connect. It is the signature step in an SoW or contingent-contract chain, not the system of record for the work itself.",
      "docs_links": [
        {
          "label": "eSignature REST API Reference",
          "url": "https://developers.docusign.com/docs/esign-rest-api/reference/"
        },
        {
          "label": "Authentication (OAuth 2.0)",
          "url": "https://developers.docusign.com/docs/esign-rest-api/esign101/auth/"
        },
        {
          "label": "JWT Grant (service integration)",
          "url": "https://developers.docusign.com/platform/auth/jwt-get-token/"
        },
        {
          "label": "Connect webhooks",
          "url": "https://developers.docusign.com/platform/webhooks/connect/"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 - JWT Grant for service integrations (no user login) or Authorization Code Grant; request the signature scope. Auth host account.docusign.com (account-d.docusign.com demo); token at POST /oauth/token; call /oauth/userinfo once to resolve the account base_uri.",
        "style": "REST, JSON; Authorization: Bearer",
        "base_url": "https://{account-base-uri}.docusign.net/restapi/v2.1/accounts/{accountId}",
        "webhooks": "DocuSign Connect - push notifications on envelope and recipient status (sent, delivered, completed, declined, voided).",
        "events_posture": "push",
        "rate_limits": "Hourly per-account request ceilings with burst allowance; 429 with backoff. /oauth/userinfo is separately rate-limited, so cache the base_uri.",
        "objects": "envelopes, documents, recipients (signers), tabs, templates, textCustomFields, Connect configurations"
      },
      "mvm": [
        {
          "object": "Envelope",
          "object_note": "Create signature request from the decision",
          "canonical": "defence_file (document), signers = approvers/business_owner, emailSubject = intent.title",
          "target": "POST /restapi/v2.1/accounts/{acct}/envelopes",
          "required": "Required",
          "notes": "status=sent to dispatch; documents supplied as base64"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Write the Intent ID onto the envelope",
          "canonical": "intent_id, intent_version",
          "target": "Envelope textCustomFields",
          "required": "Required",
          "notes": "Level-1 correlation - Intent ID recoverable from any completed envelope"
        },
        {
          "object": "Completion back-sync",
          "object_note": "Read for the intent timeline",
          "canonical": "envelope status, completedDateTime, signers[]",
          "target": "Connect webhook / GET /envelopes/{id}",
          "required": "Recommended",
          "notes": "Store the completed PDF plus the certificate of completion"
        }
      ],
      "tenant_note": "eSignature is the signature/execution step, not the system of record for the underlying work - pair it with the VMS/CLM/S2P destination that owns the engagement. DocuSign now markets the broader IAM platform; composerID targets the stable eSignature REST API. Production and demo use different base hosts, so always resolve the per-account base_uri via /oauth/userinfo."
    },
    {
      "platform": "Adobe Acrobat Sign",
      "key": "adobesign",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Adobe Acrobat Sign (REST API v6) is a signature/execution layer, the same role as DocuSign. composerID uploads the decision document as a transientDocument, creates an Agreement (optionally via a predefined workflow), stamps the Intent ID as the agreement externalId, and tracks status through v6 webhooks.",
      "docs_links": [
        {
          "label": "Acrobat Sign v6 REST API",
          "url": "https://developer.adobe.com/acrobat-sign/docs/overview/"
        },
        {
          "label": "API Usage guide",
          "url": "https://developer.adobe.com/acrobat-sign/docs/overview/developer_guide/apiusage"
        },
        {
          "label": "Webhooks (OAuth 2.0)",
          "url": "https://developer.adobe.com/acrobat-sign/docs/overview/acrobat_sign_events/webhooks-oauth-2-0"
        },
        {
          "label": "Best practices (baseUris)",
          "url": "https://developer.adobe.com/acrobat-sign/docs/overview/developer_guide/bestpractices"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 with scoped tokens (agreement_send, agreement_write, agreement_read, workflow_read) or an Integration Key bearer token for single-tenant automation. Partner apps need Adobe certification for multi-account access. Resolve the account api_access_point via GET /api/rest/v6/baseUris before other calls.",
        "style": "REST, JSON; Authorization: Bearer",
        "base_url": "https://{shard}.adobesign.com/api/rest/v6  (shard from baseUris, e.g. api.na1 / api.eu1)",
        "webhooks": "v6 webhooks - subscribe to AGREEMENT_* events; the endpoint must echo the X-AdobeSign-ClientId header to verify; 72-hour progressive retry.",
        "events_posture": "push",
        "rate_limits": "Per-minute/hour/day limits by service level; heavy operations run async; avoid polling (risks 429 / temporary API disable) - use webhooks.",
        "objects": "transientDocuments, agreements, libraryDocuments, widgets, megaSigns, workflows, webhooks, users, groups"
      },
      "mvm": [
        {
          "object": "Transient Document",
          "object_note": "Upload the decision document",
          "canonical": "defence_file / SoW draft (file)",
          "target": "POST /api/rest/v6/transientDocuments",
          "required": "Required",
          "notes": "Returns transientDocumentId used as the agreement file source"
        },
        {
          "object": "Agreement",
          "object_note": "Create the signature request",
          "canonical": "name = intent.title, participants = approvers/signers, workflowId (optional), state",
          "target": "POST /api/rest/v6/agreements",
          "required": "Required",
          "notes": "Reference the transientDocumentId; state=IN_PROCESS to send"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "agreement externalId",
          "required": "Required",
          "notes": "externalId enables lookup and POST /search back-sync"
        }
      ],
      "tenant_note": "Signature/execution layer, not the system of record for the work - chain it with the owning VMS/CLM/S2P destination. Each account resolves to a regional shard, so cache the api_access_point from baseUris. Multi-tenant (PARTNER) apps must be Adobe-certified before acting on other accounts."
    },
    {
      "platform": "Ironclad",
      "key": "ironclad",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Ironclad is a contract lifecycle system of record. composerID launches a Workflow (or writes a Repository Record) of the appropriate type - for example Statement of Work - carrying the canonical decision and the Intent ID, then tracks execution through event webhooks across signature and storage.",
      "docs_links": [
        {
          "label": "Public API - getting started",
          "url": "https://developer.ironcladapp.com/reference/getting-started-api"
        },
        {
          "label": "Authentication (OAuth 2.0)",
          "url": "https://developer.ironcladapp.com/reference/authenticate-a-request"
        },
        {
          "label": "Webhooks reference",
          "url": "https://developer.ironcladapp.com/reference/webhooks"
        },
        {
          "label": "Create a Record",
          "url": "https://developer.ironcladapp.com/docs/create-a-record-1"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 with scoped tokens (the legacy static API-token bearer was deprecated 22 Nov 2024). SCIM 2.0 for provisioning. API Access is a paid add-on/SKU.",
        "style": "REST, JSON; OpenAPI 3.1",
        "base_url": "https://{subdomain}.ironcladapp.com/public/api/v1  (regional na1 / eu1; plus preview and demo)",
        "webhooks": "Event webhooks - workflow_launched, workflow_completed, workflow_signature_packet_fully_signed, workflow_attribute_updated and more; up to 10 retries over ~13.6h; a 410 disables the subscription.",
        "events_posture": "push",
        "rate_limits": "Documented CLM API rate limits per plan; standard 429 backoff.",
        "objects": "workflows, records (repository), entities, signature packets, webhooks; a Record has type (e.g. Statement of Work), name, properties{}"
      },
      "mvm": [
        {
          "object": "Workflow",
          "object_note": "Launch a contract process",
          "canonical": "workflow type, counterparty, service_category, budget, dates",
          "target": "POST /public/api/v1/workflows",
          "required": "Required",
          "notes": "Workflow type maps to the SoW / vendor-agreement process; fetch the schema first"
        },
        {
          "object": "Record",
          "object_note": "Write a repository record",
          "canonical": "type = Statement of Work, name, properties{start_date, cost_center, budget}",
          "target": "POST /public/api/v1/records",
          "required": "Tenant",
          "notes": "Use when writing a completed contract straight to the Repository"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "workflow/record property",
          "required": "Required",
          "notes": "Property defined in Workflow Designer; drives webhook back-sync"
        }
      ],
      "tenant_note": "Record types and workflow properties are tenant-configured in Workflow Designer - confirm the SoW/vendor-agreement type keys and property names per tenant via the schema endpoints. API Access is a separately-licensed SKU; regional hosting (na1/eu1) sets the subdomain."
    },
    {
      "platform": "Icertis",
      "key": "icertis",
      "category": "Signature & Contract Management",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "Icertis Contract Intelligence (ICI) is an enterprise CLM system of record. composerID files a Contract Request / Agreement of the appropriate Contract Type, populating attributes from the canonical decision and linking the Compliance File as an Associated Document, with the Intent ID stored as an attribute for correlation.",
      "docs_links": [
        {
          "label": "Icertis API Developer Experience",
          "url": "https://developer.icertis.com/"
        },
        {
          "label": "ICI Business APIs overview",
          "url": "https://www.icertis.com/research/blog/api-clm-value/"
        },
        {
          "label": "Contract Types & Attributes",
          "url": "https://developer.icertis.com/"
        },
        {
          "label": "Obligation Management",
          "url": "https://developer.icertis.com/"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 via your IdP (Azure AD / Okta / Ping) using OIDC discovery - ICI has no native credential store; calls also carry an ici-product-key (subscription key). ICMAuthToken is test-only; Client Certificate on request.",
        "style": "REST, JSON; 200+ Business APIs with standard CRUD",
        "base_url": "Region-specific ICI Developer Experience gateway; {customerinstance}.icertis.com",
        "webhooks": "Rule/event-driven notifications plus async delivery for long-running actions (AI clause extraction, multi-step approvals); poll the GET endpoints where webhooks are not configured.",
        "events_posture": "mixed",
        "rate_limits": "Per-tenant platform limits; long-running operations are asynchronous with status polling.",
        "objects": "Agreements, Contract Types (Contract Request / Agreement / Associated Document / Masterdata), Attributes, Clauses, Templates, Masterdata, Obligations & Fulfillments, Associations"
      },
      "mvm": [
        {
          "object": "Contract Request",
          "object_note": "Assemble inputs for an agreement",
          "canonical": "contract_type, requestor, service_category, dates, budget",
          "target": "ICI Business API - create Contract Request",
          "required": "Required",
          "notes": "Contract Type is tenant-defined; attributes drive the request form"
        },
        {
          "object": "Agreement",
          "object_note": "Create the executable contract",
          "canonical": "attributes{title, counterparty, effective_date}, template",
          "target": "ICI Business API - create Agreement",
          "required": "Tenant",
          "notes": "Uses tenant Templates + Clauses; own vs third-party paper"
        },
        {
          "object": "Intent ID + evidence",
          "object_note": "Correlate and attach",
          "canonical": "intent_id (attribute), defence_file (Associated Document)",
          "target": "Agreement attribute + Associated Document",
          "required": "Required",
          "notes": "Associated Documents carry the SoW draft / questionnaires"
        }
      ],
      "tenant_note": "ICI is deeply configuration-driven: Contract Types, Attributes, Templates and Clauses are defined per tenant, so mapping needs the tenant's Contract Type schema. Business APIs are a separate SKU and require the APIM Dev Portal role plus an ici-product-key. Auth federates to the customer's IdP (Azure-native)."
    },
    {
      "platform": "PandaDoc",
      "key": "pandadoc",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "PandaDoc is a document-automation and eSignature platform with a clean public REST API. composerID creates documents from templates and stamps the Intent ID into the document's metadata, which is returned on reads and webhooks.",
      "docs_links": [
        {
          "label": "PandaDoc Developer Docs",
          "url": "https://developers.pandadoc.com/"
        },
        {
          "label": "Developer Reference",
          "url": "https://developers.pandadoc.com/reference/about"
        },
        {
          "label": "Official API client (GitHub)",
          "url": "https://github.com/PandaDoc/pandadoc-api-python-client"
        }
      ],
      "api": {
        "auth": "API key via the Authorization: API-Key <key> header, or OAuth 2.0 authorization-code flow (authorize at https://app.pandadoc.com/oauth2/authorize) for multi-workspace apps.",
        "style": "REST, JSON",
        "base_url": "https://api.pandadoc.com  (resources under /public/v1)",
        "webhooks": "Native webhook subscriptions (/public/v1/webhook-subscriptions) with a queryable webhook-events log; events fire on document state changes and recipient completion.",
        "events_posture": "push",
        "rate_limits": "Rate limited per account with HTTP 429 on exceed; back off and retry. Plan-specific limits: confirm current values in the developer docs.",
        "objects": "documents, templates, contacts, content-library-items, document-attachments, webhook-subscriptions"
      },
      "mvm": [
        {
          "object": "Document (from template)",
          "object_note": "Create a document",
          "canonical": "template_uuid, recipients[], fields/tokens",
          "target": "POST /public/v1/documents",
          "required": "Required",
          "notes": "Document generated from a template + intent data"
        },
        {
          "object": "Document status",
          "object_note": "Send for signature",
          "canonical": "document_id, status",
          "target": "POST /public/v1/documents/{id}/send",
          "required": "Tenant required",
          "notes": "Moves draft -> sent once uploaded"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "metadata on the document",
          "required": "Required",
          "notes": "PandaDoc documents carry arbitrary metadata, returned on reads and webhooks"
        },
        {
          "object": "Webhook event",
          "object_note": "Read for back-sync",
          "canonical": "event, document_id, status",
          "target": "/public/v1/webhook-subscriptions",
          "required": "Required",
          "notes": "Reconcile on document state change / recipient completion"
        }
      ],
      "tenant_note": "PandaDoc documents accept arbitrary metadata (key-value) that is returned on reads and webhooks, so the Intent ID rides natively. Templates and roles are configured per workspace; a single-workspace integration can use an API key, while multi-workspace apps use OAuth."
    },
    {
      "platform": "Dropbox Sign",
      "key": "dropboxsign",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Dropbox Sign (formerly HelloSign) is a self-service eSignature API. composerID sends agreements for signature and rides the Intent ID in the signature request's arbitrary metadata, which is returned on reads and callbacks for reconciliation.",
      "docs_links": [
        {
          "label": "Dropbox Sign API Reference",
          "url": "https://developers.hellosign.com/api/reference/overview/"
        },
        {
          "label": "Authentication",
          "url": "https://developers.hellosign.com/api/reference/authentication/"
        },
        {
          "label": "Developer docs: events & callbacks",
          "url": "https://developers.hellosign.com/docs/"
        },
        {
          "label": "Official OpenAPI spec (GitHub)",
          "url": "https://github.com/hellosign/hellosign-openapi"
        }
      ],
      "api": {
        "auth": "API key over HTTP Basic (key as the username), or an OAuth 2.0 Bearer access token (JWT) for multi-account apps. Test-mode calls are supported with the API key.",
        "style": "REST, JSON",
        "base_url": "https://api.hellosign.com/v3",
        "webhooks": "Native callbacks at account or API-app level. Events: signature_request_sent, signature_request_viewed, signature_request_signed, signature_request_all_signed, signature_request_declined, signature_request_downloadable, signature_request_canceled.",
        "events_posture": "push",
        "rate_limits": "Per-API-key rate limiting surfaced via X-RateLimit-Limit / X-RateLimit-Remaining / X-Ratelimit-Reset headers; HTTP 429 on exceed: back off and retry.",
        "objects": "signature_request, template, bulk_send_job, unclaimed_draft, team, account, api_app, report"
      },
      "mvm": [
        {
          "object": "Signature Request",
          "object_note": "Send an agreement for signature",
          "canonical": "signer, document, subject, message",
          "target": "POST /signature_request/send",
          "required": "Required",
          "notes": "Ad-hoc eSignature engagement"
        },
        {
          "object": "Signature Request from Template",
          "object_note": "Templated agreement",
          "canonical": "template_id, signers[], custom_fields",
          "target": "POST /signature_request/send_with_template",
          "required": "Tenant required",
          "notes": "Reusable templates configured per account"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "metadata[intent_id] on the signature request",
          "required": "Required",
          "notes": "Dropbox Sign metadata is arbitrary key-value, returned on reads and callbacks"
        },
        {
          "object": "Callback event",
          "object_note": "Read for back-sync",
          "canonical": "event_type, signature_request_id, status",
          "target": "account / API-app callback_url",
          "required": "Required",
          "notes": "Used for reconciliation"
        }
      ],
      "tenant_note": "Metadata keys are arbitrary and echoed on reads and callbacks, so the Intent ID rides natively. Account-level callbacks are self-service; app-level callbacks require an API App. OAuth is only needed for apps acting on behalf of multiple accounts."
    },
    {
      "platform": "Ivalua",
      "key": "ivalua",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "Ivalua is a unified source-to-pay suite - a system of record for sourcing, contracts, orders and invoices - with a highly configurable open data model. composerID publishes the canonical decision into the relevant object (Sourcing event, Contract, or Requisition/Order) via Ivalua's REST services and Integration Hub, carrying the Intent ID for correlation.",
      "docs_links": [
        {
          "label": "Ivalua Open Ecosystem",
          "url": "https://www.ivalua.com/technology/ivalua-open-ecosystem/"
        },
        {
          "label": "Procurement Platform / Integration Hub",
          "url": "https://www.ivalua.com/technology/procurement-platform/"
        },
        {
          "label": "Multi-ERP Integration",
          "url": "https://www.ivalua.com/solutions/business/multi-erp-integration/"
        }
      ],
      "api": {
        "auth": "Customer-provisioned API keys; SSO via SAML/OIDC for user contexts. Access is enabled per customer (an API key is issued on request).",
        "style": "REST web services, JSON & XML; also AS2 / SFTP / HTTPS batch; Integration Hub + Console for orchestration and monitoring",
        "base_url": "Per-tenant Ivalua instance (customer-specific host)",
        "webhooks": "Integration Hub orchestration plus Integration Console transaction monitoring; event / ETL / EAI patterns rather than a single public webhook catalog.",
        "events_posture": "mixed",
        "rate_limits": "Tenant/deployment-specific; governed via the Integration Console.",
        "objects": "Suppliers, Sourcing/RFx, Contracts, Requisitions, Orders, Invoices, Catalogs, Items, Performance evaluations (open, configurable data model)"
      },
      "mvm": [
        {
          "object": "Sourcing / RFx",
          "object_note": "Open a sourcing event",
          "canonical": "service_category, sow.summary, dates, budget",
          "target": "Ivalua Sourcing REST service",
          "required": "Tenant",
          "notes": "For competitively-sourced services"
        },
        {
          "object": "Contract",
          "object_note": "Create or land a contract",
          "canonical": "counterparty, dates, budget, terms",
          "target": "Ivalua Contract REST service",
          "required": "Tenant",
          "notes": "Object/field names follow the tenant's configured data model"
        },
        {
          "object": "Requisition / Order",
          "object_note": "Commit spend",
          "canonical": "cost_center, amount, supplier, start_date",
          "target": "Ivalua Requisition/Order REST service",
          "required": "Tenant",
          "notes": "Read Orders/Invoices back for reconciliation"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Custom field on the sourcing / requisition object",
          "required": "Required",
          "notes": "Ivalua's data model is customer-extended; field key agreed at onboarding"
        }
      ],
      "tenant_note": "Ivalua's data model is highly configurable per client - object and field names are not fixed across tenants, so mapping requires each customer's configured schema and an issued API key. The full REST API reference is provided to customers/partners rather than via a public developer portal; the Open Ecosystem page is the public entry point."
    },
    {
      "platform": "JAGGAER",
      "key": "jaggaer",
      "category": "Vendor Management & Sourcing",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "JAGGAER ONE is a source-to-pay suite (Sourcing, Supplier Management, Contracts, eProcurement) - a system of record for procurement. composerID publishes the canonical decision via JAGGAER's REST/JSON services (request/response or event-driven push), carrying the Intent ID for correlation; cXML handles transactional documents where used.",
      "docs_links": [
        {
          "label": "JAGGAER Integrations (Trust Center)",
          "url": "https://www.jaggaer.com/trustcenter/integrations/"
        },
        {
          "label": "Integration via JAGGAER Public APIs (PDF)",
          "url": "https://www.jaggaer.com/wp-content/uploads/2024/06/JAGGAER-Integration-via-JAGGAER-Public-APIs.pdf"
        },
        {
          "label": "Advanced Sourcing Optimizer API",
          "url": "https://asodocs.jaggaer.com/"
        },
        {
          "label": "Supplier Identity Management (SSO)",
          "url": "https://www.jaggaer.com/solutions/supplier-identity-management"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 - generate a Client ID + Client Secret in the JAGGAER admin panel; client_credentials grant for system-to-system bearer tokens (e.g. ASO). cXML SharedSecret (HMAC) for document exchange; SAML/OIDC for supplier SSO.",
        "style": "REST services, JSON messaging (request/response or push); cXML for punchout/PO/invoice; SAP-certified (S/4HANA, ECC)",
        "base_url": "Per-tenant JAGGAER ONE host; ASO at asodocs.jaggaer.com",
        "webhooks": "Event-driven (push) REST services in addition to request/response; supplier and document events.",
        "events_posture": "push",
        "rate_limits": "Tenant-specific; bulk endpoints for large loads.",
        "objects": "Sourcing events, Contracts, Suppliers, Requisitions/Orders (eProcurement), Spend records; ASO optimization events/jobs"
      },
      "mvm": [
        {
          "object": "Sourcing Event",
          "object_note": "Open a sourcing / RFx event",
          "canonical": "service_category, sow.summary, dates, budget",
          "target": "JAGGAER Sourcing REST service (ASO for optimization)",
          "required": "Tenant",
          "notes": "For competitive services sourcing"
        },
        {
          "object": "Contract",
          "object_note": "Create a contract",
          "canonical": "counterparty, dates, budget, terms",
          "target": "JAGGAER Contracts REST service",
          "required": "Tenant",
          "notes": "Source-to-contract module"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "Custom field / external reference on the object",
          "required": "Required",
          "notes": "Enables back-sync via push events"
        }
      ],
      "tenant_note": "JAGGAER ONE integration specifics (object/field names, available REST services) are largely provided to customers/partners; the ASO API and the Integration via Public APIs guide are the public entry points. OAuth client credentials are generated per-tenant in the admin panel; cXML SharedSecrets have no rotation API, so schedule manual rotation."
    },
    {
      "platform": "SAP SuccessFactors",
      "key": "successfactors",
      "category": "HRIS / HCM",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "SAP SuccessFactors is the HRIS/HCM system of record - the anchor destination for the permanent-hiring channel. composerID publishes the decision as a Position (Employee Central) and, where Recruiting is live, a Job Requisition, stamps the Intent ID on a custom field, and reconciles the eventual hire (EmpJob) back onto the intent timeline.",
      "docs_links": [
        {
          "label": "SAP Business Accelerator Hub - SuccessFactors",
          "url": "https://api.sap.com/products/SAPSuccessFactors"
        },
        {
          "label": "OData v2 - Authentication using OAuth 2.0",
          "url": "https://help.sap.com/docs/successfactors-platform/sap-successfactors-api-reference-guide-odata-v2/authentication-using-oauth-2-0"
        },
        {
          "label": "SuccessFactors Platform docs (API guides)",
          "url": "https://help.sap.com/docs/successfactors-platform"
        },
        {
          "label": "KBA 3462403 - OData OAuth 2.0 walkthrough",
          "url": "https://userapps.support.sap.com/sap/support/knowledge/en/3462403"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 SAML Bearer Assertion - register an OAuth client in Admin Center (Manage OAuth 2.0 Client Applications, X.509 certificate), exchange the signed assertion at POST /oauth/token (grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer, company_id + API key as client_id). HTTP Basic for OData/SFAPI is deprecated and is removed in November 2026 (KBA 3462403). The API user also needs matching Role-Based Permissions - a token alone is not enough.",
        "style": "OData v2 (primary; $batch for bulk) plus newer OData v4 APIs; REST/JSON",
        "base_url": "https://{api-server}.successfactors.com/odata/v2  (per data center; .eu hosts for EU DCs)",
        "webhooks": "Intelligent Services Center events + Integration Center outbound; otherwise delta-query on lastModifiedDateTime.",
        "events_posture": "mixed",
        "rate_limits": "Tenant-level concurrency/throughput limits (not publicly numeric); 429/503 with backoff; prefer $batch.",
        "objects": "Position, FOCostCenter, PerPerson, EmpEmployment, EmpJob, User, picklists (Employee Central); JobRequisition, JobApplication, JobOffer, Candidate (Recruiting)"
      },
      "mvm": [
        {
          "object": "Position",
          "object_note": "Create/approve the position to hire against",
          "canonical": "title, cost_center_id, start_date, location",
          "target": "OData v2 upsert Position (Employee Central)",
          "required": "Required",
          "notes": "Position Management anchors the perm decision"
        },
        {
          "object": "Job Requisition",
          "object_note": "Open the requisition in Recruiting",
          "canonical": "role_title, location, hiring_manager, openings",
          "target": "OData JobRequisition (Recruiting module)",
          "required": "Tenant",
          "notes": "Template-driven; Recruiting is separately licensed"
        },
        {
          "object": "Intent ID + hire back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id (cust_ custom field); EmpJob on hire",
          "target": "Custom field + Intelligent Services event",
          "required": "Required",
          "notes": "The hire event closes the loop on the intent timeline"
        }
      ],
      "tenant_note": "SuccessFactors is heavily tenant-configured: MDF objects, picklists and requisition templates differ per tenant, so mapping needs each tenant's schema. API servers are per data center; the OAuth client is registered per instance and the API user must hold matching Role-Based Permissions. Recruiting (JobRequisition) is a separately licensed module - confirm before planning the requisition step."
    },
    {
      "platform": "Greenhouse",
      "key": "greenhouse",
      "category": "ATS",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Greenhouse is an ATS - the recruiting system of record on the permanent-hiring channel. composerID creates the Job from a tenant-designated template with its Openings, carries the Intent ID as the queryable requisition_id plus custom fields, and back-syncs offer and hire events through signed webhooks.",
      "docs_links": [
        {
          "label": "Harvest API v3 (latest)",
          "url": "https://harvestdocs.greenhouse.io"
        },
        {
          "label": "Harvest API reference (v1/v2)",
          "url": "https://developers.greenhouse.io/harvest.html"
        },
        {
          "label": "Create or update a job via Harvest",
          "url": "https://support.greenhouse.io/hc/en-us/articles/360029266072-Create-or-update-a-job-with-Harvest-API"
        },
        {
          "label": "Greenhouse API overview",
          "url": "https://support.greenhouse.io/hc/en-us/articles/10568627186203-Greenhouse-API-overview"
        }
      ],
      "api": {
        "auth": "Harvest API keys over HTTP Basic (key as username, blank password), created per-integration with per-endpoint permissions in Dev Center; every write requires an On-Behalf-Of header carrying an active Greenhouse user ID. Harvest v3 moves to OAuth 2.0 - v1/v2 are deprecated after 31 Aug 2026, so build against v3.",
        "style": "REST, JSON (Harvest v1/v2 today, v3 latest); separate public Job Board API for published posts",
        "base_url": "https://harvest.greenhouse.io/v1  (v2/v3 for select endpoints; v3 docs at harvestdocs.greenhouse.io)",
        "webhooks": "UI-configured (Dev Center > Web Hooks); HMAC-SHA256 Signature header with a shared secret; events incl. job created/updated, offer created/approved, candidate hired.",
        "events_posture": "push",
        "rate_limits": "50 requests per 10 seconds per key; 429 with X-RateLimit-Limit/-Remaining headers (no Retry-After - back off client-side).",
        "objects": "jobs, openings, job_posts, candidates, applications, offers, scorecards, users, departments, offices, custom_fields"
      },
      "mvm": [
        {
          "object": "Job",
          "object_note": "Create the job from a template",
          "canonical": "role_title, department, office, openings count; requisition_id = intent_id",
          "target": "POST /v1/jobs (template_job_id)",
          "required": "Required",
          "notes": "requisition_id is queryable (GET /v1/jobs?requisition_id=...) - a natural Intent ID carrier"
        },
        {
          "object": "Openings",
          "object_note": "Headcount to fill",
          "canonical": "opening_ids (per-seat), cost_center, budget",
          "target": "POST /v1/jobs/{id}/openings",
          "required": "Required",
          "notes": "Opening custom fields carry per-seat data"
        },
        {
          "object": "Custom fields + hire back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id/intent_version (custom fields); offer + hire events",
          "target": "PATCH job custom_fields (immutable field key) + signed webhooks",
          "required": "Required",
          "notes": "candidate_hired / offer events update the intent timeline"
        }
      ],
      "tenant_note": "Harvest keys are provisioned per integration with granular endpoint permissions - request only what publishing needs, and route writes On-Behalf-Of a real (integration system) user for audit attribution. Job creation copies a tenant-designated template job (scorecards and hiring teams cannot be set via API), and custom job field values need a follow-up PATCH. Sandbox and production have different object IDs and keys. Harvest v1/v2 sunset after 31 Aug 2026 - target v3 (OAuth 2.0)."
    },
    {
      "platform": "SAP S/4HANA",
      "key": "s4hana",
      "category": "ERP",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "SAP S/4HANA is the ERP - the financial-commitment system of record and the anchor destination for the outsourced work-order channel. composerID publishes the decision as a Purchase Requisition (or a Purchase Order with Enhanced Limit items for services), carries the Intent ID in a Key User Extensibility custom field, and reconciles PO changes and Service Entry Sheets back onto the intent timeline.",
      "docs_links": [
        {
          "label": "SAP Business Accelerator Hub - S/4HANA Cloud",
          "url": "https://api.sap.com/products/SAPS4HANACloud"
        },
        {
          "label": "Purchase Requisition (OData V4)",
          "url": "https://help.sap.com/docs/SAP_S4HANA_CLOUD/bb9f1469daf04bd894ab2167f8132a1a/dad2402e2ff543e7971d788bf35b12c1.html"
        },
        {
          "label": "Purchase Order (OData V4)",
          "url": "https://help.sap.com/docs/SAP_S4HANA_CLOUD/bb9f1469daf04bd894ab2167f8132a1a/c89eec80ec2043d980cb7b8c89e0a00a.html"
        },
        {
          "label": "S/4HANA Cloud documentation",
          "url": "https://help.sap.com/docs/SAP_S4HANA_CLOUD"
        }
      ],
      "api": {
        "auth": "Communication Management: a Communication Arrangement binds a Communication Scenario (e.g. SAP_COM_0102 Purchase Requisition Integration, SAP_COM_0053 Purchase Order) to a Communication System + Communication User; Basic or OAuth 2.0 per scenario - OAuth recommended for production. Writes need a CSRF token (x-csrf-token: fetch on a GET, replay on the POST).",
        "style": "OData v4 (current) and OData v2 (legacy; the v2 Purchase Order API is deprecated); SOAP for selected scenarios; $batch supported",
        "base_url": "https://{tenant}-api.s4hana.ondemand.com/sap/opu/odata/sap/{API_NAME}  (also *.s4hana.cloud.sap)",
        "webhooks": "Business events via SAP Event Mesh / Advanced Event Mesh; otherwise poll with $filter on LastChangeDateTime.",
        "events_posture": "mixed",
        "rate_limits": "Tenant-governed; OData paging defaults to 1000 with $top up to 5000 on PO reads; use $batch, and simulation mode (PurReqnDoOnlyValidation) as a free preflight.",
        "objects": "A_PurchaseRequisitionHeader/Item (+ account assignment, texts), Purchase Order (item categories incl. Standard, Subcontracting, Third-Party, Enhanced Limit for services), Service Entry Sheet (Lean Services), Business Partner / Supplier, cost centers"
      },
      "mvm": [
        {
          "object": "Purchase Requisition",
          "object_note": "Raise the demand",
          "canonical": "description, service_category, cost_center, budget, dates",
          "target": "POST A_PurchaseRequisitionHeader (API_PURCHASEREQ_PROCESS_SRV / OData V4)",
          "required": "Required",
          "notes": "PurReqnDoOnlyValidation=true validates without posting - use as mapping preflight"
        },
        {
          "object": "Purchase Order",
          "object_note": "Commit the spend",
          "canonical": "supplier, amount, currency, dates; Enhanced Limit item for services",
          "target": "Purchase Order OData V4 API",
          "required": "Tenant",
          "notes": "Enhanced Limit items model outsourced work orders"
        },
        {
          "object": "Intent ID + back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id (custom field); PO changes + Service Entry Sheets",
          "target": "Key User Extensibility custom field + Event Mesh / delta poll",
          "required": "Required",
          "notes": "Service Entry Sheets confirm delivered work against the PO"
        }
      ],
      "tenant_note": "Nothing is callable until the matching Communication Scenario (e.g. SAP_COM_0102 / SAP_COM_0053) is bound to a Communication System and User in a Communication Arrangement - API access is switched on per tenant. Intent ID custom fields are added with Key User Extensibility (Custom Fields app, header/item business contexts). Target the OData V4 services (the v2 PO API is deprecated). On-premise S/4HANA differs: Gateway service activation instead of communication arrangements."
    },
    {
      "platform": "Oracle",
      "key": "oracle",
      "category": "ERP",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Oracle Fusion Cloud ERP/Procurement is a financial-commitment system of record for the outsourced work-order channel. composerID raises a Purchase Requisition (or Purchase Order, where policy allows) through the Fusion REST APIs, carries the Intent ID in a Descriptive Flexfield, and reconciles PO lifecycle changes back onto the intent timeline.",
      "docs_links": [
        {
          "label": "REST API for Oracle Fusion Cloud Procurement",
          "url": "https://docs.oracle.com/en/cloud/saas/procurement/"
        },
        {
          "label": "Purchase Orders REST endpoints",
          "url": "https://docs.oracle.com/en/cloud/saas/procurement/25c/fapra/api-purchase-orders.html"
        },
        {
          "label": "Purchase Requisitions REST endpoints",
          "url": "https://docs.oracle.com/en/cloud/saas/procurement/20b/fapra/api-purchase-requisitions.html"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 via OCI IAM identity domains - create a confidential application (client credentials for server-to-server, or JWT/certificate assertion); the Client ID must also exist as a Fusion user with the right roles. Basic auth works but fails once MFA is enforced - treat OAuth as the production path.",
        "style": "REST, JSON (ADF-based resources; newer BOSS v1 endpoints use /api/boss/... paths); offset/limit pagination with hasMore",
        "base_url": "https://{instance}.fa.{datacenter}.oraclecloud.com/fscmRestApi/resources/{version}  (e.g. 11.13.18.05)",
        "webhooks": "ERP business events consumed via Oracle Integration (OIC) or polling; no plain public webhook registry on the REST resources themselves.",
        "events_posture": "mixed",
        "rate_limits": "Throttled per identity domain (unofficially ~5,000 calls/hour/user); 429 on breach - keep publishing transactional, use FBDI/bulk paths for volume.",
        "objects": "purchaseRequisitions (header/lines + submit action), purchaseOrders (+ communicateOnePurchaseOrder and other actions), draft POs, suppliers, receipts; Descriptive Flexfields (DFFs) on both PR and PO"
      },
      "mvm": [
        {
          "object": "Purchase Requisition",
          "object_note": "Raise the demand",
          "canonical": "description, service_category, cost_center, budget, dates",
          "target": "POST /fscmRestApi/resources/{v}/purchaseRequisitions (+ submit-for-approval action)",
          "required": "Required",
          "notes": "Preparer coupling: the API user must be the requisition preparer (error POR-2010915 otherwise)"
        },
        {
          "object": "Purchase Order",
          "object_note": "Commit the spend",
          "canonical": "supplier, amount, currency, dates",
          "target": "purchaseOrders REST resource",
          "required": "Tenant",
          "notes": "Direct PO create/communicate where program policy allows"
        },
        {
          "object": "Intent ID + back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id (DFF attribute); PO/receipt changes",
          "target": "Descriptive Flexfield + ERP business events via OIC / delta polling",
          "required": "Required",
          "notes": "DFFs carry the correlation on both PR and PO"
        }
      ],
      "tenant_note": "Auth is per identity domain: register the confidential app in OCI IAM and mirror its Client ID as a Fusion user with matching roles - a token alone is not enough. Version strings matter (resources exist in multiple versions; newer BOSS v1 endpoints use a different path shape). DFF segments are tenant-configured, so agree the Intent ID segment name per tenant. The API user must be a valid preparer for requisition creation."
    },
    {
      "platform": "Microsoft Dynamics 365",
      "key": "dynamics365",
      "category": "ERP",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Dynamics 365 Finance & Supply Chain is a financial-commitment system of record for the outsourced work-order channel. composerID publishes Purchase Order entities through the OData endpoint, carries the Intent ID via an extended field on the entity, and back-syncs create/update/delete activity through Business Events and Data Events.",
      "docs_links": [
        {
          "label": "OData endpoint (finance & operations)",
          "url": "https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/odata"
        },
        {
          "label": "Data entities overview",
          "url": "https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/data-entities"
        },
        {
          "label": "Data events (CUD notifications)",
          "url": "https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/business-events/data-events"
        }
      ],
      "api": {
        "auth": "Microsoft Entra ID (Azure AD) OAuth 2.0 client credentials - register the app, then map the App ID to a user in the environment (Microsoft Entra applications form). Tokens ~1h; the resource is the environment URL (no trailing slash).",
        "style": "OData v4 REST over data entities (entities marked IsPublic); $filter/$select/$batch; page size max 1,000; cross-company=true for non-default legal entities",
        "base_url": "https://{environment}.operations.dynamics.com/data",
        "webhooks": "Business Events + Data Events (per-entity create/update/delete) delivered to Azure Event Grid, Service Bus, HTTPS or Power Automate; Data Events require the Power Platform integration to be enabled.",
        "events_posture": "push",
        "rate_limits": "Service-protection throttling; ~600 requests/min is the practical guidance; 429 with Retry-After - back off exponentially. Use the Data Management Framework for bulk.",
        "objects": "PurchaseOrderHeadersV2 / PurchaseOrderLinesV2, purchase requisitions, VendorsV2, and any IsPublic data entity (incl. custom entities for extended fields)"
      },
      "mvm": [
        {
          "object": "Purchase Order",
          "object_note": "Commit the spend",
          "canonical": "supplier (OrderVendorAccountNumber), amounts, dates, legal entity (dataAreaId)",
          "target": "POST /data/PurchaseOrderHeadersV2 (+ Lines)",
          "required": "Required",
          "notes": "All entity-key fields must be supplied; cross-company=true when publishing outside the default company"
        },
        {
          "object": "Requisition (where used)",
          "object_note": "Raise demand upstream of the PO",
          "canonical": "description, cost_center, budget",
          "target": "Purchase requisition data entities",
          "required": "Tenant",
          "notes": "Many programs publish straight to PO for outsourced work orders"
        },
        {
          "object": "Intent ID + back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id (extended field); CUD events on the PO entity",
          "target": "Entity extension field + Data/Business Events to Event Grid/Service Bus",
          "required": "Required",
          "notes": "Data events emit the full entity record on change"
        }
      ],
      "tenant_note": "Nothing works until the Entra app is mapped to an environment user with the right security roles. Custom fields ride on entity extensions (or custom data entities) - agree the Intent ID field per tenant. Data Events require Power Platform integration on the environment; environments without it fall back to Business Events or polling. OData is for transactional volume - bulk loads belong in the Data Management Framework."
    },
    {
      "platform": "NetSuite",
      "key": "netsuite",
      "category": "ERP",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "NetSuite is the dominant mid-market cloud ERP - a financial-commitment system of record for the outsourced work-order channel. composerID creates the Purchase Order through SuiteTalk REST, carries the Intent ID in a custom body field, and reconciles with SuiteQL reads (and SuiteScript-relayed events, since NetSuite has no native webhooks).",
      "docs_links": [
        {
          "label": "OAuth 2.0 for REST web services",
          "url": "https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157780312610.html"
        },
        {
          "label": "NetSuite documentation (Oracle Help)",
          "url": "https://docs.oracle.com/en/cloud/saas/netsuite/index.html"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 (client credentials at /services/rest/auth/oauth2/v1/token, or authorization code) tied to an Integration Record + Role; legacy Token-Based Auth (OAuth 1.0a HMAC) still works but is being phased out and cannot be used with 2FA roles. Tokens inherit the role's permissions and subsidiary restrictions.",
        "style": "SuiteTalk REST (record/v1 CRUD: GET/POST/PATCH/DELETE) + SuiteQL (query/v1/suiteql, SQL-like reads with Prefer: transient); SOAP is legacy (deprecation trajectory ~2028)",
        "base_url": "https://{accountId}.suitetalk.api.netsuite.com/services/rest  (sandbox accounts use {accountId}_SB1)",
        "webhooks": "None native - relay events with SuiteScript user-event scripts posting outbound, or reconcile by polling SuiteQL on lastModifiedDate.",
        "events_posture": "none",
        "rate_limits": "~10 concurrent requests per account on REST plus volume throttling; batch reads through SuiteQL.",
        "objects": "purchaseOrder, vendor, vendorBill, item/expense lines, subsidiaries; custom body/column fields (custbody_/custcol_); REST record browser at /record/v1/metadata-catalog"
      },
      "mvm": [
        {
          "object": "Purchase Order",
          "object_note": "Commit the spend",
          "canonical": "supplier (entity), lines (items/expenses), dates, subsidiary",
          "target": "POST /services/rest/record/v1/purchaseOrder",
          "required": "Required",
          "notes": "PATCH for partial updates; role must span the target subsidiary in OneWorld"
        },
        {
          "object": "Status & bill read-back",
          "object_note": "Track receipt and billing",
          "canonical": "PO status, vendor bills, amounts",
          "target": "POST /services/rest/query/v1/suiteql",
          "required": "Recommended",
          "notes": "SuiteQL is the read layer (transaction/transactionLine)"
        },
        {
          "object": "Intent ID + back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id (custbody field); changes since last sync",
          "target": "custbody_intent_id + SuiteScript event relay or lastModifiedDate polling",
          "required": "Required",
          "notes": "No native webhooks - plan the relay or the poll from day one"
        }
      ],
      "tenant_note": "Every NetSuite account's schema diverges: custom fields, forms and scripts differ per tenant, so mapping needs the tenant's record model (custbody_ field for the Intent ID agreed up front). Tokens inherit role permissions and OneWorld subsidiary restrictions - provision a dedicated integration role. OAuth 2.0 authorizations are not copied into sandbox refreshes; re-authorize after each refresh. Deep record catalogs sit behind the NetSuite Help Center login."
    },
    {
      "platform": "ADP",
      "key": "adp",
      "category": "HRIS / HCM",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "ADP Workforce Now is a payroll-anchored HRIS system of record for the permanent-hiring channel. composerID posts the hire through the Applicant Onboard V2 API, carries the Intent ID in a worker custom field, and closes the loop by subscribing to worker event notifications.",
      "docs_links": [
        {
          "label": "ADP API guides (developers.adp.com)",
          "url": "https://developers.adp.com/guides/api-guides"
        },
        {
          "label": "Workforce Now API catalog",
          "url": "https://developers.adp.com/articles/guides/adp-workforce-now-api-catalog"
        },
        {
          "label": "API Central for Workforce Now",
          "url": "https://apps.adp.com/en-US/apps/410612/adp-api-central-for-adp-workforce-now-and-adp-workforce-now-next-generation/features"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 client credentials plus a mutual-TLS client certificate on every call (certificates requested and rotated in the API Central portal); OpenID Connect underneath. Access itself is provisioned - API Central is a purchasable add-on per client, or a Marketplace partner agreement.",
        "style": "REST, JSON, event-message envelopes for writes; canonical URIs must be added to the app's scope in the Consumer Application Registry before an API is callable",
        "base_url": "https://api.adp.com  (tokens from https://accounts.adp.com)",
        "webhooks": "Event notifications - subscribe to worker events (hire, change, terminate) to trigger back-sync pulls.",
        "events_posture": "push",
        "rate_limits": "Per-subscription throttling; hire processing is slow (can exceed 20s and time out at the gateway) - design submits as async with status polling.",
        "objects": "Applicant Onboard V2, Workers v2 (reads; SSN/birth masked unless masked=false), Workers Life Cycle Management (start/cancel hire, change hire date), custom fields (category 3), validation tables, event notifications"
      },
      "mvm": [
        {
          "object": "Applicant Onboard",
          "object_note": "Post the hire into WFN",
          "canonical": "person, job/position, department, start_date, pay group",
          "target": "Applicant Onboard V2 API (in-progress or completed hire)",
          "required": "Required",
          "notes": "The older Worker Hire Event API (/events/hr/v1/worker.hire) is deprecated - target V2"
        },
        {
          "object": "Worker record + custom fields",
          "object_note": "Enrich and read back",
          "canonical": "associateOID, assignment, cost identifiers",
          "target": "Workers v2 + custom-field APIs (category 3)",
          "required": "Tenant",
          "notes": "Sensitive fields are masked by default"
        },
        {
          "object": "Intent ID + hire back-sync",
          "object_note": "Correlate and reconcile",
          "canonical": "intent_id (worker custom field); worker.hire notifications",
          "target": "Custom field + event-notification subscription",
          "required": "Required",
          "notes": "Onboard processing is async in practice - reconcile on the event, not the response"
        }
      ],
      "tenant_note": "Everything is provisioned: the client buys API Central (or you integrate as a Marketplace partner), each API's canonical URI is added to the application's registry scope, and calls need the mTLS certificate as well as the bearer token. Templates and mandatory fields (Group, state tax fields) vary per WFN configuration - preflight against the /meta endpoints. Most reference documentation sits behind the developer login."
    },
    {
      "platform": "Lever",
      "key": "lever",
      "category": "ATS",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Lever is an ATS with a candidate-centric (Opportunity) model - the recruiting system of record on the permanent-hiring channel. composerID creates the Requisition with requisitionCode = Intent ID, opens the Posting against it, and back-syncs offers and hires through signed webhooks and archive-as-hired-against-requisition.",
      "docs_links": [
        {
          "label": "Lever Data API documentation",
          "url": "https://hire.lever.co/developer/documentation"
        },
        {
          "label": "API changelog",
          "url": "https://hire.lever.co/developer/updates"
        },
        {
          "label": "Public Postings API (job boards)",
          "url": "https://github.com/lever/postings-api"
        }
      ],
      "api": {
        "auth": "API key over HTTP Basic (key as username) for private integrations - keys carry per-endpoint permissions and an explicit confidential-data grant set at creation; OAuth 2.0 (1-hour tokens) for partner apps, EU instances supported. Writes attribute to a real user via the perform_as parameter.",
        "style": "REST, JSON at /v1; offset-token pagination (opaque next tokens); separate unauthenticated v0 Postings API for public job boards",
        "base_url": "https://api.lever.co/v1  (EU instance and sandbox available)",
        "webhooks": "UI-configured with a signing token; HMAC-SHA256 signature delivered in the request body (verify + cache tokens against replay). Events incl. candidate hired, stage change, archive, interviews, contacts. Persistent endpoint failures disable the webhook - ack fast, process async.",
        "events_posture": "push",
        "rate_limits": "10 req/s per key (token bucket, ~20 burst); POSTs throttle lower (~2/s); 429 with Retry-After.",
        "objects": "requisitions (requisitionCode, headcountTotal, compensationBand, customFields, approvals), postings, opportunities (candidate-centric), applications, offers (incl. signed documents), archive reasons, requisition_fields"
      },
      "mvm": [
        {
          "object": "Requisition",
          "object_note": "Open the approved demand",
          "canonical": "requisitionCode = intent_id, name, headcountTotal, compensationBand, customFields",
          "target": "POST /v1/requisitions",
          "required": "Required",
          "notes": "requisitionCode is queryable - the natural Intent ID carrier"
        },
        {
          "object": "Posting",
          "object_note": "Publish the role",
          "canonical": "role_title, team, location, requisitionCodes[]",
          "target": "POST /v1/postings?perform_as={userId}",
          "required": "Required",
          "notes": "API-created postings skip the approval chain unless created as drafts"
        },
        {
          "object": "Hire back-sync",
          "object_note": "Close the loop",
          "canonical": "offer signed, candidate hired against the requisition",
          "target": "Signed webhooks + archived-as-hired (requisitionId)",
          "required": "Required",
          "notes": "Hiring against a requisition ties the Opportunity back to the Intent ID"
        }
      ],
      "tenant_note": "Key scoping is decided at creation: endpoint permissions and confidential-data access cannot be widened later without a new key - request exactly what publishing needs. Requisition custom fields are tenant-defined (requisition_fields endpoint). Webhook signatures arrive in the body, not a header, and Lever disables webhooks after sustained failures - return 200 immediately and queue. EU tenants live on the EU instance."
    },
    {
      "platform": "Juro",
      "key": "juro",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Juro is a browser-native contract automation and e-signature platform where templates, smartfields, approval flows and signing live in one workspace. composerID publishes into Juro by creating a contract from a named template and populating its smartfields, so the paperwork for a decision already taken is drafted and routed for signature without anyone re-keying it. Juro is the execution and evidence layer for that decision, not the system that makes it.",
      "docs_links": [
        {
          "label": "Juro API documentation (OpenAPI reference)",
          "url": "https://api-docs.juro.com/"
        },
        {
          "label": "Working with Juro's API",
          "url": "https://intercom.help/juro/en/articles/8075637-working-with-juro-s-api"
        },
        {
          "label": "Adding and using smartfields",
          "url": "https://intercom.help/juro/en/articles/5652971-adding-and-using-smartfields"
        },
        {
          "label": "Webhooks",
          "url": "https://juro.com/integrations/webhooks"
        },
        {
          "label": "Juro API overview",
          "url": "https://juro.com/integrations/api"
        }
      ],
      "api": {
        "auth": "API key sent as an x-api-key request header. The key is issued per account from Settings &rarr; Integrations &rarr; API &amp; webhooks.",
        "style": "REST/JSON with a published OpenAPI specification. Collection pagination uses skip and limit query parameters (limit defaults to 50, maximum 200).",
        "base_url": "https://api.juro.com/v3 (a sandbox at api-sandbox.juro.io is available on request, not self-serve)",
        "webhooks": "Native push webhooks. Subscriptions are registered in-app under Settings &rarr; Integrations &rarr; API &amp; webhooks and deliver asynchronous notifications across the contract lifecycle - creation, views, approvals and signature - with the fully-signed PDF passable downstream. Confirm the current event list and payload-signing scheme against the API docs when wiring a tenant.",
        "events_posture": "push",
        "rate_limits": "Documented as a tiered monthly request quota plus a per-second throttle with a short burst allowance; the quota depends on the account's API tier, so confirm the tenant's limits against the published tiers before planning batch volume.",
        "objects": "Contracts (/v3/contracts, plus /v3/contracts/upload to create from an existing PDF), templates (referenced by templateId on create), smartfields (fields[] addressed by uid), Q&amp;A answers (answers[]), signatories and counterparties, webhook subscriptions."
      },
      "mvm": [
        {
          "object": "Contract (create from template)",
          "object_note": "POST /v3/contracts with a templateId and a body carrying fields[] and answers[]",
          "canonical": "title",
          "target": "Contract name (commonly driven by the counterparty legal name smartfield, which names both the contract and the signing side)",
          "required": "Required",
          "notes": "The template determines which smartfields exist; the create call fills them by uid, not by display label."
        },
        {
          "object": "Contract &rarr; reference smartfield",
          "object_note": "A text smartfield added to the template to carry the external reference",
          "canonical": "intent_id",
          "target": "fields[].uid = the reference field's uid, fields[].value = the Intent ID",
          "required": "Tenant required",
          "notes": "Juro's public docs describe no first-class external-ID or metadata property on the contract object, so the Intent ID rides a purpose-built smartfield agreed per tenant. It reads back on GET and on webhook payloads, which is what makes re-publishing idempotent."
        },
        {
          "object": "Contract &rarr; counterparty",
          "object_note": "Counterparty legal entity and signatory details",
          "canonical": "counterparty",
          "target": "Counterparty legal name smartfield plus signatory smartfields / Q&amp;A answers",
          "required": "Required",
          "notes": "Smartfields are filled either by the owner at create time or by the counterparty answering a Q&amp;A flow before signing - decide per template which side owns each field."
        },
        {
          "object": "Contract &rarr; commercial terms",
          "object_note": "Date- and choice-typed smartfields on the template",
          "canonical": "start_date, end_date, value",
          "target": "Date and text smartfields addressed by uid",
          "required": "Tenant",
          "notes": "Choice-type smartfields reject values outside the template's allowed list, so any composerID enumeration must be reconciled against the template's choices before first publish."
        },
        {
          "object": "Webhook subscription",
          "object_note": "Lifecycle events pushed back for reconciliation",
          "canonical": "defence_file_ref",
          "target": "Consumer endpoint, correlated on the reference smartfield returned in the payload",
          "required": "Recommended",
          "notes": "Signature and lifecycle events close the loop; the signed PDF is what the audit spine's evidence reference points at."
        }
      ],
      "tenant_note": "Everything material is template-scoped and therefore per-customer: which templates exist, which smartfields they carry, each smartfield's uid and type (text, date or choice) and, for choice fields, the permitted values. Whether a smartfield is filled by the publisher at create time or by the counterparty in the pre-signing Q&amp;A is also a template decision. Because no generic external-ID slot is documented, each tenant must agree a dedicated reference smartfield for the Intent ID before go-live. Webhook endpoints, the signing secret and the API tier are configured in the customer's own Juro account."
    },
    {
      "platform": "Agiloft",
      "key": "agiloft",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Agiloft is a no-code CLM built on a knowledgebase of user-definable tables, records, rules and workflows - the contract table is one instance of that model rather than a fixed schema. composerID publishes into Agiloft by creating a contract record in the customer's knowledgebase and setting the fields their configuration requires, so an approved decision becomes a tracked record moving through the tenant's own approval and signature workflow. Agiloft records, routes and enforces the agreement; the decision about what to buy and from whom is made upstream.",
      "docs_links": [
        {
          "label": "REST Interface",
          "url": "https://help.agiloft.com/space/HELP/43715778/REST+Interface"
        },
        {
          "label": "Using OAuth2 to access the REST API",
          "url": "https://help.agiloft.com/space/HELP/43716464/Using+OAuth2+to+Access+REST+API"
        },
        {
          "label": "REST - Read",
          "url": "https://help.agiloft.com/space/HELP/43714567/REST+-+Read"
        },
        {
          "label": "Webhooks",
          "url": "https://help.agiloft.com/space/HELP/43714342/Webhooks"
        },
        {
          "label": "Agiloft Developer Guide (PDF)",
          "url": "https://www.agiloft.com/documentation/agiloft-developer-guide.pdf"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 is the documented modern path: an API application registered inside the knowledgebase defines the grant type, the user account whose permissions govern data access, and the client identifier, and a token exchange yields a bearer token. ExtAuth remains as a legacy mechanism, and the classic interface accepts credentials as $login / $password parameters or a session token from EWLogin.",
        "style": "REST over HTTP in an operation-per-endpoint style (EWCreate, EWUpdate, EWSelect, EWDelete, EWLogin, EWLock, EWAttach) rather than resource-oriented REST, with a parallel SOAP web-services API offering equivalent operations. The classic interface is XML-oriented.",
        "base_url": "Tenant-hosted: https://{instance}.agiloft.com/ewws/{operation} - every call carries the knowledgebase as $KB and the target table as $table",
        "webhooks": "Outbound webhooks are an administrator-configured feature registered under Setup &rarr; Integration &rarr; Webhook Setup; each fires on record created, record updated or both, and carries HTTP headers the administrator supplies. There is no fixed event catalogue and no documented payload-signing mechanism, so authenticate the callback with a header and treat event coverage as a per-knowledgebase decision. The Workato-based Integration Hub provides further event-driven paths.",
        "events_posture": "mixed",
        "rate_limits": "None published. Agiloft documents no request quotas, throttling or concurrency caps; practical limits follow the customer's hosting tier and knowledgebase configuration and should be confirmed with Agiloft per deployment.",
        "objects": "Knowledgebase tables and their records addressed by logical table name - in a CLM knowledgebase principally the contract/agreement table, plus companies and parties, people and contacts, attachments and approval records. Workflow transitions and action buttons can also be triggered through the interface."
      },
      "mvm": [
        {
          "object": "Contract record (create)",
          "object_note": "EWCreate against the knowledgebase's contract table, addressed by its logical $table name",
          "canonical": "title",
          "target": "Contract title field on the contract table",
          "required": "Required",
          "notes": "The table's logical name and the field's internal name are both knowledgebase-specific and differ from the display labels administrators see in the UI."
        },
        {
          "object": "Contract record &rarr; reference field",
          "object_note": "A custom text field added to the contract table for the publisher's reference",
          "canonical": "intent_id",
          "target": "Custom single-line text field (knowledgebase-defined; no standard external-ID field is documented)",
          "required": "Tenant required",
          "notes": "Because knowledgebases are user-definable by design, the Intent ID needs a purpose-added text field - ideally searchable via EWSelect so a re-publish looks up the existing record instead of creating a duplicate."
        },
        {
          "object": "Contract record &rarr; counterparty",
          "object_note": "Usually a linked-field relationship to the companies table rather than free text",
          "canonical": "counterparty",
          "target": "Company / party linked field on the contract record",
          "required": "Tenant",
          "notes": "Linked fields resolve against an existing record in the related table, so publishing may need a look-up-or-create step against companies before the contract create call succeeds."
        },
        {
          "object": "Contract record &rarr; term and value",
          "object_note": "Date and currency fields, or Key Term records, on the contract table",
          "canonical": "start_date, end_date, value",
          "target": "Contract start date, end date and value fields (knowledgebase-named)",
          "required": "Tenant",
          "notes": "Agiloft models key terms such as contract title and start date as their own records, so a knowledgebase may expect these as key-term rows as well as, or instead of, plain fields. Confirm which per tenant."
        },
        {
          "object": "Webhook subscription",
          "object_note": "Setup &rarr; Integration &rarr; Webhook Setup, scoped to the contract table",
          "canonical": "defence_file_ref",
          "target": "Outbound POST on record created or updated, correlated on the reference field",
          "required": "Recommended",
          "notes": "The webhook is enabled by the customer's administrator rather than by the API client, so event delivery is provisioned during onboarding rather than assumed."
        }
      ],
      "tenant_note": "Agiloft is configuration-first, so almost nothing about the contract schema is universal. Per customer, confirm: the knowledgebase name ($KB) and the contract table's logical name ($table); the internal field names, which differ from display labels; which fields the knowledgebase marks mandatory, since the API rejects a create that leaves any unsatisfied; whether counterparties are linked records or text; whether commercial terms live in plain fields or key-term records; and which custom text field carries the Intent ID. The user account registered against the OAuth application governs record-level permissions, so a publish can fail on visibility rules rather than on payload shape. Webhook registration is an administrator action inside the customer's own knowledgebase."
    },
    {
      "platform": "Conga CLM",
      "key": "conga",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Conga CLM is an enterprise contract-lifecycle platform of Apttus lineage, shipped in two materially different deployments: CLM for Salesforce (a managed package running inside the customer's own Salesforce org) and CLM on the Conga Advantage Platform (Conga-hosted REST APIs). composerID publishes into Conga by creating or amending an Agreement record once a decision has been taken, carrying the Intent ID onto that record so the paper reconciles back to the decision. Conga records and progresses the agreement; it is not the system that decided the engagement should happen.",
      "docs_links": [
        {
          "label": "Conga Developer Portal - Contracts (CLM REST reference)",
          "url": "https://developer.conga.com/contracts/"
        },
        {
          "label": "Advantage Platform - REST API introduction",
          "url": "https://developer.conga.com/platform/reference/rest-api-introduction"
        },
        {
          "label": "Authenticating Agreement Services APIs (CLM for Salesforce)",
          "url": "https://documentation.conga.com/en/clm-for-salesforce/current/clm-for-rest-api-developers/authenticating-agreement-services-apis"
        },
        {
          "label": "CLM SOAP API reference (Agreement Web Service)",
          "url": "https://documentation.conga.com/en/clm-for-salesforce/current/clm-for-soap-api-developers/api-reference"
        },
        {
          "label": "CLM for Advantage Platform - documentation",
          "url": "https://documentation.conga.com/en/clm-for-advantage-platform/current"
        }
      ],
      "api": {
        "auth": "Deployment-dependent, and the two are not interchangeable. Advantage Platform: OAuth 2.0 client credentials - a Conga API Connection issues a client ID and secret, exchanged for a bearer token with roughly an hour's lifetime. CLM for Salesforce: authentication is Salesforce's own OAuth 2.0 against the customer org (the legacy SOAP surface authenticates via an Apttus login call first).",
        "style": "Advantage Platform: REST/JSON with resource-oriented URLs and HTTP status codes for errors. CLM for Salesforce is Salesforce-platform-based, which changes both auth and object model - the surface is Salesforce REST/SOAP over managed-package objects plus Conga Apex REST services, so a publisher connects to the customer's Salesforce org rather than a Conga-hosted tenant. A SOAP Agreement Web Service covers activate, select-template and publish operations. Pagination conventions are not publicly documented.",
        "base_url": "Advantage Platform: https://rls.congacloud.com/api/clm/v1/... &middot; CLM for Salesforce: https://{myorg}.force.com/services/apexrest/Apttus/clm/{version}/{API} alongside the org's standard Salesforce REST endpoints",
        "webhooks": "No CLM-specific webhook or event-subscription API is publicly documented. Webhooks are documented for adjacent Conga products (Conga Sign event notifications, and the separate Novatus-lineage Conga Contracts) - do not assume they cover CLM. Salesforce-hosted deployments can use Salesforce-native Platform Events and Change Data Capture, but that is a Salesforce capability rather than a Conga-documented CLM one, so confirm the event path per deployment.",
        "events_posture": "mixed",
        "rate_limits": "None published for CLM on either deployment. For CLM for Salesforce the binding constraint is the customer's own Salesforce org limits, including per-transaction governor limits and total org API calls per rolling 24 hours; no limits are documented for the Conga-hosted endpoints.",
        "objects": "Advantage Platform CLM v1: contracts (create-offline, amend, activate, terminate), contract clauses, supporting documents, document generation and preview, reviews. CLM for Salesforce: the managed-package Agreement object and its related clause, template and document records, exposed via Salesforce REST/SOAP plus the Agreement Web Service."
      },
      "mvm": [
        {
          "object": "Agreement / contract record",
          "object_note": "Advantage Platform: create against the CLM v1 contracts resource. Salesforce: insert the managed-package Agreement object, then use the Agreement Web Service to select a template and generate.",
          "canonical": "title",
          "target": "Contract / agreement name",
          "required": "Required",
          "notes": "The publish target is the agreement record itself; document generation is a second step against the created record rather than part of creation."
        },
        {
          "object": "Agreement &rarr; reference field",
          "object_note": "Carrier for the Intent ID",
          "canonical": "intent_id",
          "target": "Tenant-defined custom field on the agreement record (on Salesforce, optionally flagged as an External ID)",
          "required": "Tenant required",
          "notes": "No standard external-reference field is documented on either deployment. On Salesforce the External ID pattern gives genuine idempotent upsert-by-key - a Salesforce platform capability, not a Conga feature; on the Advantage Platform, treat create as non-idempotent and reconcile by search."
        },
        {
          "object": "Agreement &rarr; counterparty",
          "object_note": "Account or party association",
          "canonical": "counterparty",
          "target": "Account / party record referenced by the agreement",
          "required": "Required",
          "notes": "Salesforce deployments resolve to a Salesforce Account; Advantage Platform deployments to the platform's account record. Either way the counterparty must pre-exist or be created first, so agree a look-up-or-create strategy per tenant."
        },
        {
          "object": "Agreement &rarr; commercial terms",
          "object_note": "Term and value fields on the agreement header",
          "canonical": "start_date, end_date, value",
          "target": "Contract term start and end dates, contract value",
          "required": "Tenant",
          "notes": "Field API names differ between the managed package and the Advantage Platform contract model, and are commonly extended per customer - confirm against the tenant's schema rather than mapping generically."
        },
        {
          "object": "Supporting document",
          "object_note": "Attach the decision record alongside the paper",
          "canonical": "defence_file_ref",
          "target": "Supporting document on the contract record (Advantage Platform), or the publish-document operations on the Agreement Web Service (Salesforce)",
          "required": "Recommended",
          "notes": "Keeps the rationale travelling with the agreement so an auditor reading the contract can reach the decision behind it."
        }
      ],
      "tenant_note": "The first question on any Conga engagement is which Conga CLM this is: the Salesforce managed package or CLM on the Conga Advantage Platform. They differ in authentication, base URL and object model, and a connector built for one does not work against the other. Conga's estate also contains several similarly named contract products (Conga Contracts and Conga Contracts for Salesforce are a different lineage again), so confirm the product, not just the vendor. Beyond that, the Intent ID carrier field, the agreement record type, the generation template and the approval path are all tenant-configured; on Salesforce deployments the customer's org API limits and managed-package version also constrain throughput."
    },
    {
      "platform": "Evisort (Workday Contract Intelligence)",
      "key": "evisort",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "Evisort is an AI-native contract intelligence and lifecycle platform, acquired by Workday and now marketed as Workday Contract Intelligence, powered by Evisort AI. composerID publishes into it by raising a ticket against a published workflow - the same intake path a human would use - so a decision already taken becomes a contract request that Evisort's workflow, review and extraction layers execute against. It is the paper and intelligence layer for that decision, not the system that makes it.",
      "docs_links": [
        {
          "label": "Evisort developer portal",
          "url": "https://developers.evisort.com/"
        },
        {
          "label": "Workflow API - intake forms, workflows, tickets",
          "url": "https://workflow.developers.evisort.com/"
        },
        {
          "label": "Documents API - metadata, fields and provisions",
          "url": "https://documents.developers.evisort.com/metadata"
        },
        {
          "label": "Admin API",
          "url": "https://admin.developers.evisort.com/"
        },
        {
          "label": "Workday Contract Intelligence, powered by Evisort AI",
          "url": "https://www.workday.com/en-us/products/contract-management/contract-intelligence.html"
        }
      ],
      "api": {
        "auth": "An API key minted by the user in the Evisort UI is exchanged for a short-lived JWT, which is then presented as a bearer token on subsequent calls. No OAuth 2.0 authorization-code or client-credentials flow is publicly documented, so the integration identity is a named user's key - agree ownership and rotation before go-live.",
        "style": "REST/JSON versioned at /v1, split across separately documented surfaces rather than one monolith: Documents, Workflow, Admin and Audit Logs. Independently hosted rather than Salesforce-platform-based. Pagination conventions are not publicly documented.",
        "base_url": "https://api.evisort.com/v1 - a single host, with tenancy resolved by the API key rather than a per-customer subdomain",
        "webhooks": "No webhook or event-subscription API appears in the public developer documentation. The nearest event surface is the Audit Logs API, which exposes a read-only view of events within a workspace - a pull surface, not a push one. Plan on polling ticket and document state, or the audit log, for status back.",
        "events_posture": "poll",
        "rate_limits": "None published. Limits appear to be enforced server-side, so handle 429 responses and agree expected throughput with the tenant rather than assuming headroom.",
        "objects": "Workflow API: intake forms and their field options, published workflows, tickets (create, get, update), ticket documents, ticket judgments, activities. Documents API: document upload (new document and new version), field update on a document, and metadata endpoints listing fields and provisions. Admin and Audit Logs APIs cover users and workspace audit events."
      },
      "mvm": [
        {
          "object": "Ticket",
          "object_note": "Create a ticket against a published workflow - the primary publish target, and how an external system raises a contract request",
          "canonical": "title",
          "target": "Ticket name / the corresponding intake-form field",
          "required": "Required",
          "notes": "The payload is shaped by the selected workflow's intake form, so composerID reads the intake form and its field options for the target workflow rather than posting a fixed body."
        },
        {
          "object": "Ticket &rarr; reference field",
          "object_note": "Carrier for the Intent ID",
          "canonical": "intent_id",
          "target": "Tenant-configured intake-form field on the workflow, mirrored onto the resulting document as a custom field",
          "required": "Tenant required",
          "notes": "No standard external-reference or idempotency-key field is documented on tickets or documents, so the field must exist on the published workflow's intake form before composerID can publish, and duplicate suppression is the publisher's responsibility."
        },
        {
          "object": "Ticket &rarr; counterparty",
          "object_note": "Counterparty capture at intake",
          "canonical": "counterparty",
          "target": "Counterparty / party intake-form field",
          "required": "Tenant",
          "notes": "Whether this is free text, a picklist or a lookup depends entirely on how the workflow was authored - read the intake form's field options before mapping."
        },
        {
          "object": "Document fields",
          "object_note": "Write structured metadata onto the resulting contract document",
          "canonical": "start_date, end_date, value, owner",
          "target": "Document metadata fields and provisions",
          "required": "Tenant",
          "notes": "Field names are case-sensitive on update, and the tenant's field set must be enumerated first. Supplied values also compete with Evisort's own AI extraction, so precedence between provided and extracted values is a tenant decision."
        },
        {
          "object": "Ticket document",
          "object_note": "Attach the decision record to the request",
          "canonical": "defence_file_ref",
          "target": "Document attached to the ticket, or a version uploaded against the record",
          "required": "Recommended",
          "notes": "Stores the rationale with the contract so the extraction layer and any later auditor both see why the engagement was approved."
        }
      ],
      "tenant_note": "Nearly everything a publisher touches here is tenant-authored: which workflows are published, what fields their intake forms expose and in what shape, and which document metadata fields and provisions exist. composerID discovers the target workflow, reads its intake form and field options, and enumerates document fields per customer rather than mapping to a fixed schema. The Intent ID carrier field has to be added to the intake form by the customer's administrator before publishing can work. API keys are minted per user in the UI, so the integration identity and its rotation are a customer-side decision - and following the Workday acquisition, confirm whether the tenant is on standalone Evisort or Workday-provisioned Contract Intelligence, since that governs provisioning and identity."
    },
    {
      "platform": "LinkSquares",
      "key": "linksquares",
      "category": "Signature & Contract Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "LinkSquares splits contract lifecycle management across Finalize (pre-signature intake, drafting and workflow) and Analyze (a post-signature repository whose AI extracts metadata from executed documents). Which half composerID publishes into changes the payload materially: Finalize takes a request or draft for the legal team to pick up, Analyze takes an executed document plus the metadata the source system already knows. Either way LinkSquares is the paper and evidence layer for a decision taken upstream, and it carries the Intent ID so the agreement traces back to the intent that caused it.",
      "docs_links": [
        {
          "label": "LinkSquares API overview",
          "url": "https://help.linksquares.com/hc/en-us/articles/10575707057175-LinkSquares-API-Overview"
        },
        {
          "label": "Managing API keys and authenticating",
          "url": "https://help.linksquares.com/hc/en-us/articles/10575849523735-Managing-API-Keys-and-Authenticating-to-the-LinkSquares-APIs"
        },
        {
          "label": "Finalize API technical overview",
          "url": "https://help.linksquares.com/hc/en-us/articles/10820768071063-Finalize-API-Technical-Overview"
        },
        {
          "label": "Analyze API sample use cases",
          "url": "https://help.linksquares.com/hc/en-us/articles/10849398433559-Analyze-API-Sample-Use-Cases"
        },
        {
          "label": "API and SDK reference guide (OpenAPI 3.0)",
          "url": "https://help.linksquares.com/hc/en-us/articles/10550275687063-LinkSquares-API-and-SDK-Reference-Guide"
        }
      ],
      "api": {
        "auth": "Static API key sent as an x-api-key request header over HTTPS. Keys are generated by administrators and each is bound to one user and one company, so provision a service account rather than reusing a named user. No OAuth flow is documented.",
        "style": "REST/JSON with a published OpenAPI 3.0 specification, distributed as a downloadable file rather than a hosted spec. Analyze list endpoints use cursor-based pagination rather than page numbers. Document upload is a two-step flow: create the metadata record, then PUT the file to a returned pre-signed URL.",
        "base_url": "https://api.linksquares.com - a single shared host with product-scoped, versioned paths (analyze and finalize are versioned independently); tenancy resolves from the API key rather than a subdomain",
        "webhooks": "No vendor-documented webhook or event-subscription surface. The Finalize API is described in terms of reading agreement status and version updates, which is a pull model, so plan on polling the agreement endpoints with a cursor for change detection unless the vendor confirms an event surface for the tenant.",
        "events_posture": "poll",
        "rate_limits": "Documented and specific: 15 requests per second with a burst of 30, returning a rate-exceeded error beyond that. No separate daily or monthly quota is published.",
        "objects": "Analyze: agreements (create/import, retrieve, list), agreement documents via pre-signed URL, and metadata - AI-extracted smart values, terms including custom user-generated values, types, tags and parent-child hierarchy. Finalize: agreements and requests, agreement detail fields, attachments, versions, and owner assignment by user ID."
      },
      "mvm": [
        {
          "object": "Agreement (Finalize)",
          "object_note": "Pre-signature draft or intake request raised from an external system for the legal team to pick up",
          "canonical": "title, counterparty, start_date, end_date, value, owner",
          "target": "Finalize agreement or request, plus its agreement detail fields",
          "required": "Tenant",
          "notes": "Which agreement detail fields exist, and which are mandatory, is tenant-configured per template. Owner assignment is by user ID, so composerID resolves a LinkSquares user rather than passing an email string."
        },
        {
          "object": "Agreement (Analyze)",
          "object_note": "Post-signature import of an executed document into the repository, where extraction then runs over it",
          "canonical": "title, counterparty, start_date, end_date, value",
          "target": "Analyze agreement record; supplied values land alongside the AI-extracted smart values",
          "required": "Required",
          "notes": "Agreement type and tags are required on import. Supplied metadata is stored as a user-generated value rather than overwriting the AI's extraction, so precedence per field has to be agreed with the customer."
        },
        {
          "object": "Agreement &rarr; reference field",
          "object_note": "Carrier for the Intent ID",
          "canonical": "intent_id",
          "target": "A dedicated custom term in Analyze, or a dedicated agreement detail field in Finalize",
          "required": "Tenant required",
          "notes": "There is no first-class external-ID field on the agreement; vendor guidance is to store an external identifier as a custom term. Provision a text field of at least 64 characters before go-live, or the Intent ID has nowhere to live."
        },
        {
          "object": "Document",
          "object_note": "The paper itself, uploaded to the pre-signed URL returned on create",
          "canonical": "defence_file_ref",
          "target": "Document uploaded via pre-signed URL, or an attachment on an existing Finalize agreement",
          "required": "Recommended",
          "notes": "Because upload is a second call, publishing is not atomic: treat metadata-created-but-file-missing as a retryable state and key retries on the Intent ID so a retry does not create a second agreement."
        },
        {
          "object": "Status readback",
          "object_note": "Reconciliation after publish",
          "canonical": "intent_id",
          "target": "Read the agreement, matched on the stored Intent ID",
          "required": "Read",
          "notes": "With no documented webhooks, reconciliation is a scheduled poll - budget it against the 15 requests/second ceiling and use cursor pagination rather than re-walking the repository."
        }
      ],
      "tenant_note": "Agreement detail fields in Finalize and terms in Analyze are per-tenant configuration, so the field carrying the Intent ID must be provisioned by the customer's administrator before publishing is enabled. Agreement types and tags are also tenant-defined and required on Analyze import, so a valid vocabulary has to be agreed per customer. Commercially, the Finalize public API reads as an add-on rather than part of the base subscription - confirm the customer has actually licensed API access before scoping. API keys are per user per company, so provision a dedicated service account."
    },
    {
      "platform": "Sirion",
      "key": "sirion",
      "category": "Signature & Contract Management",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "Sirion is an enterprise AI-native CLM covering authoring, negotiation, a central repository and post-signature obligation, SLA and supplier-performance management. Its B2B API is designed so that what can be done in the web application can be done through the API, so composerID publishes by creating a contract draft request and, where configured, triggering the e-signature flow. Sirion turns a decision into a governed, auditable agreement and then holds the obligations that follow from it; the decision itself is made upstream.",
      "docs_links": [
        {
          "label": "Self-serve integrations - B2B API and Workato connector",
          "url": "https://www.sirion.ai/sirion-university/integrations/self-serve-integrations/"
        },
        {
          "label": "Sirion integrations overview",
          "url": "https://www.sirion.ai/integrations/"
        },
        {
          "label": "Release 2.84 - OAuth client setup for B2B API token permissions",
          "url": "https://www.sirion.ai/library/whats-new/sirion-release-284/"
        },
        {
          "label": "Release 2.87 - integration and webhook updates",
          "url": "https://www.sirion.ai/library/whats-new/sirion-release-287/"
        },
        {
          "label": "Sirion CLM integration with SAP Ariba (SAP Business Accelerator Hub)",
          "url": "https://api.sap.com/package/SirionContractLifecycleManagementCLMIntegrationwithSAPAribaProcurement/overview"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 client credentials. A Sirion administrator generates client credentials for the B2B APIs and shares the client ID and secret with the integrator; token permissions and scopes are configured in the platform's OAuth client setup. Vendor guidance is a least-privilege integration principal with TLS 1.2 or better, IP allow-listing and regular credential rotation.",
        "style": "REST/JSON. Pagination conventions are not published. A vendor-published Workato connector and webhook triggers exist alongside the raw API, and in some estates integration is expected to route through that connector rather than direct REST calls.",
        "base_url": "Per-customer tenant hostname, supplied by the customer's Sirion administrator - there is no published subdomain or path pattern, and the SAP Ariba integration guide likewise takes the tenant hostname as a configuration parameter",
        "webhooks": "Native webhook events are documented at feature level: real-time triggers on contract changes, approvals and milestone events, plus job-status updates for bulk operations. Webhook rules can filter on static and custom select fields, so a tenant can scope events to composerID-originated records. No public event catalogue or payload schema exists, so treat the callback as a signal and re-read the contract before updating the audit spine.",
        "events_posture": "push",
        "rate_limits": "No numeric limits published. Release notes confirm limits exist and are token-type dependent (limits for external-type tokens were raised to support heavier integration workloads), but no values are published - agree throughput with the customer's Sirion team.",
        "objects": "Contracts, contract draft requests, templates (template list and metadata, including an external ID on templates), custom fields, e-signature requests, obligations and SLA/performance records, suppliers, users and role groups, plus bulk import jobs."
      },
      "mvm": [
        {
          "object": "Contract draft request",
          "object_note": "The pre-signature intake object - the natural landing point for a decision made but not yet papered",
          "canonical": "title, counterparty, start_date, end_date, value, owner",
          "target": "Contract draft request with its template-driven static and custom fields",
          "required": "Tenant",
          "notes": "Mandatory fields follow the selected template and tenant configuration. Administrators control whether extraction fields create custom fields on contracts or on draft requests, so the same logical field may exist on one object and not the other."
        },
        {
          "object": "Contract",
          "object_note": "The repository record against which obligations and SLAs are subsequently tracked",
          "canonical": "title, counterparty, start_date, end_date, value",
          "target": "Contract record - core fields plus tenant-defined custom fields",
          "required": "Tenant",
          "notes": "Publishing straight to the contract skips the draft and approval workflow, which suits importing an already-executed agreement but not one Sirion is meant to author. Confirm which path is enabled before mapping."
        },
        {
          "object": "Contract &rarr; reference field",
          "object_note": "Carrier for the Intent ID",
          "canonical": "intent_id",
          "target": "A dedicated custom field on the contract or draft request",
          "required": "Tenant required",
          "notes": "Sirion's own integration guidance recommends external IDs as correlation keys so replays and retries upsert rather than creating new records. Templates expose an external ID, but whether the contract object does is unconfirmed, so provision an explicit custom field rather than relying on it."
        },
        {
          "object": "E-signature request",
          "object_note": "Sending the papered agreement out for execution",
          "canonical": "counterparty, owner",
          "target": "E-signature request raised through the B2B API against the drafted contract",
          "required": "Optional",
          "notes": "The underlying signature provider and routing are tenant-configured, so trigger the Sirion-side action rather than integrating the signature vendor directly."
        },
        {
          "object": "Webhook subscription",
          "object_note": "Closing the loop back to the Intent Record",
          "canonical": "defence_file_ref",
          "target": "Webhook rule filtered on contract status, approval or milestone changes",
          "required": "Recommended",
          "notes": "Because rules filter on custom select fields, events can be scoped to composerID-originated records rather than the whole estate."
        }
      ],
      "tenant_note": "Almost everything a publisher touches here is tenant configuration: the tenant hostname, the OAuth client and its token scopes, the contract templates and their static and custom field sets, and the webhook rules and filters. The custom field carrying the Intent ID must be created by the customer's administrator and its system name confirmed before publishing is enabled. Rate limits are token-type dependent and unpublished, so throughput is agreed rather than assumed. Confirm too whether the customer is licensed for B2B API access and whether integration is expected to route through the vendor's Workato connector instead of direct REST calls."
    },
    {
      "platform": "Gatekeeper",
      "key": "gatekeeper",
      "category": "Signature & Contract Management",
      "docs_confidence": "Customer",
      "generated": true,
      "summary": "Gatekeeper is a vendor and contract lifecycle platform whose data model gives suppliers equal standing with contracts, wrapped in a Kanban workflow engine. Publishing into it usually means resolving or creating the vendor first, then the contract - and often raising a workflow card rather than writing to the repository directly. Gatekeeper is the system of record and execution for a decision taken upstream; what makes it different from a pure CLM is that the counterparty is a first-class object, not a field on the contract.",
      "docs_links": [
        {
          "label": "Configuring the Gatekeeper API (auth, API keys, per-tenant reference)",
          "url": "https://knowledge.gatekeeperhq.com/en/docs/configuring-api"
        },
        {
          "label": "Integrations, including webhooks",
          "url": "https://knowledge.gatekeeperhq.com/en/docs/integrations"
        },
        {
          "label": "Configure custom data",
          "url": "https://knowledge.gatekeeperhq.com/en/docs/configuring-custom-data-fields"
        },
        {
          "label": "Contract dates",
          "url": "https://knowledge.gatekeeperhq.com/en/docs/contract-dates"
        },
        {
          "label": "Gatekeeper Interconnect - integration overview",
          "url": "https://www.gatekeeperhq.com/gatekeeper-interconnect"
        }
      ],
      "api": {
        "auth": "An API key issued per tenant, presented as a bearer token in the Authorization header. Keys are generated under the tenant's configuration settings and carry per-endpoint permissions, so calling an endpoint the key has not been granted returns an error - a publish key must be granted exactly the vendor, contract, custom-data and webhook endpoints it needs.",
        "style": "REST over HTTPS following the JSON:API specification. Custom data groups configured in the tenant are exposed through the API, and the API reference adapts automatically as that custom data changes - so the callable field set genuinely differs tenant to tenant.",
        "base_url": "Tenant subdomain: https://{subdomain}.gatekeeperhq.com/api/ - the authoritative endpoint reference lives inside the tenant itself at /api_docs",
        "webhooks": "Native webhooks, documented in the knowledgebase: each webhook can send notifications for one or many events to the same endpoint, for example firing when a vendor record is updated, and events are included on all plans. Payload schemas, signature verification and retry behaviour are not published, so confirm them against the tenant's own reference.",
        "events_posture": "push",
        "rate_limits": "None published. Assume limits exist and confirm against the tenant's own API reference before designing a bulk publish.",
        "objects": "Suppliers and vendors alongside contracts as the two first-class records, plus workflow cards on the Kanban engine, custom data groups and fields, events and webhooks."
      },
      "mvm": [
        {
          "object": "Supplier / vendor",
          "object_note": "A first-class record; a contract normally hangs off one, so resolve-or-create the vendor before publishing the contract",
          "canonical": "counterparty",
          "target": "Supplier / vendor record",
          "required": "Required",
          "notes": "This is the mapping difference versus a pure CLM. Agree a matching strategy per customer - duplicate vendor creation is the main publish risk on this platform."
        },
        {
          "object": "Contract",
          "object_note": "The contract record created in the repository as the execution artefact of the decision",
          "canonical": "title, owner",
          "target": "Contract title, plus internal owner and vendor-side owner",
          "required": "Required",
          "notes": "Gatekeeper models two owner roles - an internal subject-matter expert and a counterparty-side contact. composerID's owner maps to the internal one; confirm whether the vendor-side owner must also be supplied."
        },
        {
          "object": "Contract &rarr; dates",
          "object_note": "Date fields drive dashboards, expiry metrics and automated renewal workflows, so date quality matters more than in a passive repository",
          "canonical": "start_date, end_date",
          "target": "Start date, and either an end date or an evergreen indicator with its notice terms",
          "required": "Required",
          "notes": "End date and the evergreen indicator are mutually exclusive - the publisher decides which it is asserting rather than sending both."
        },
        {
          "object": "Contract &rarr; custom data field",
          "object_note": "Carrier for the Intent ID",
          "canonical": "intent_id",
          "target": "A tenant-configured custom data field, exposed automatically through the API",
          "required": "Tenant required",
          "notes": "Because custom data groups flow through to the API and its reference, a dedicated field is the documented-shaped route. No native external-reference field was verified, so reading that field back is how a publisher de-duplicates."
        },
        {
          "object": "Workflow card",
          "object_note": "The Kanban engine supports creating records from form data, with triggers, checklists and approvals",
          "canonical": "value, defence_file_ref",
          "target": "Workflow card fields, contract value, and an attachment or URL custom field",
          "required": "Tenant",
          "notes": "Whether composerID should write a repository record directly or raise a workflow card is a per-customer design decision with governance consequences - confirm it before mapping."
        }
      ],
      "tenant_note": "Gatekeeper is deeply tenant-configured: custom data groups and fields, workflow phases, approval routines and notification rules are all defined per customer, and because the API and its reference adapt automatically to custom data, the field set genuinely differs between tenants. The base URL is the customer's own subdomain and the authoritative reference lives inside the tenant, which is also where the API key is displayed - so scoping this integration needs tenant access rather than a public portal. Confirm the vendor-matching rule, whether publishing should create a repository record or a workflow card, and the tenant's rate-limit behaviour before go-live."
    },
    {
      "platform": "ServiceNow",
      "key": "servicenow",
      "category": "ITSM / Service Management",
      "docs_confidence": "Public",
      "generated": true,
      "summary": "ServiceNow is the one destination where the journey can both start and finish: the Triage diagnostic runs as a Service Portal / Employee Center widget in the requester's existing session, and composerID publishes the decision back into the same instance. Writes go through the Import Set API with a transform map that coalesces on correlation_id (the task table's standard field for external-system identifiers) so a replayed publish updates the existing record instead of creating a duplicate. Catalog requests go through the Service Catalog API, never raw Table API inserts.",
      "docs_links": [
        {
          "label": "Table API (REST)",
          "url": "https://www.servicenow.com/docs/r/api-reference/rest-apis/c_TableAPI.html"
        },
        {
          "label": "Import Set API (REST)",
          "url": "https://www.servicenow.com/docs/r/api-reference/rest-apis/c_ImportSetAPI.html"
        },
        {
          "label": "Service Catalog API (REST)",
          "url": "https://www.servicenow.com/docs/r/api-reference/rest-apis/c_ServiceCatalogAPI.html"
        },
        {
          "label": "Updating records using coalesce",
          "url": "https://www.servicenow.com/docs/r/integrate-applications/system-import-sets/c_ImportSetCoalesce.html"
        }
      ],
      "api": {
        "auth": "OAuth 2.0 or basic auth against a dedicated integration user flagged web-service-access-only, with a scoped least-privilege role plus snc_platform_rest_api_access. Inbound client-credentials grant requires enabling it on the instance (Washington DC and later).",
        "style": "REST, JSON or XML (Table API, Import Set API, Service Catalog API)",
        "base_url": "https://{instance}.service-now.com/api",
        "webhooks": "None native. Outbound events are customer-built Business Rules calling RESTMessageV2 asynchronously: at-most-once delivery, so reconciliation polling on sys_updated_on is the correctness mechanism, not a fallback.",
        "events_posture": "mixed",
        "rate_limits": "Per-instance inbound REST rate limits and concurrency semaphores (instance-configurable); asynchronous outbound waits are capped at 30 seconds (glide.http.outbound.max_timeout).",
        "objects": "task (correlation_id), sc_request, sc_req_item, sn_hr_core_case, import set staging tables"
      },
      "mvm": [
        {
          "object": "Record (via Import Set)",
          "object_note": "Idempotent create-or-update",
          "canonical": "role_title, description, requested_for, cost_center, dates",
          "target": "POST /api/now/import/{staging_table} → transform map",
          "required": "Required",
          "notes": "The transform map coalesces on correlation_id: a replayed publish updates the existing record, never duplicates it"
        },
        {
          "object": "Intent ID correlation",
          "object_note": "Carry the Intent ID",
          "canonical": "intent_id, intent_version",
          "target": "correlation_id on the target task record",
          "required": "Required",
          "notes": "Standard task-table field for external-system identifiers (string, max 100); index it in the tenant for reconciliation reads"
        },
        {
          "object": "Catalog request",
          "object_note": "Order a catalog item",
          "canonical": "catalog_item, variables{}",
          "target": "POST /api/sn_sc/servicecatalog/items/{sys_id}/order_now",
          "required": "Tenant required",
          "notes": "Catalog variables live in sc_item_option / sc_item_option_mtom: never insert sc_req_item rows directly via the Table API"
        },
        {
          "object": "Record read-back",
          "object_note": "Read for reconciliation",
          "canonical": "state, assignment_group, sys_updated_on",
          "target": "GET /api/now/table/{table}?sysparm_query=correlation_id={intent_id}",
          "required": "Required",
          "notes": "Poll-first: outbound Business Rules are at-most-once, so drift detection reads back by correlation_id"
        }
      ],
      "tenant_note": "Each ServiceNow instance is a separate tenant with its own tables, ACLs and transform maps. A scoped custom table extending task changes the customer's App Engine licensing position under ServiceNow's Custom Table Guide: verify the entitlement (paid Store apps carry their own tables' entitlement) before committing to a table design. ACLs fail silently on field reads: a publish can 201 while individual fields were dropped, which preflight must catch."
    }
  ]
}
