Skip to main content
This walkthrough uses the sandbox environment. You will create a demo session, connect both platforms, read reconciled data, and clean up. No production credentials required.

Prerequisites

Set your base URL:
export API_BASE=https://api.structural.app

Step 1: Create a demo session

curl -X POST "$API_BASE/api/v1/demo/session" \
 -H "Content-Type: application/json"
{
  "data": {
    "api_key": "sk_demo_a1b2c3d4e5f6g7h8",
    "customer_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}
Save the API key - it is returned exactly once and cannot be retrieved again:
export API_KEY=sk_demo_a1b2c3d4e5f6g7h8

Step 2: Connect Procore

curl -X POST "$API_BASE/api/v1/connect" \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer $API_KEY" \
 -d '{"platform": "procore"}'
{
  "data": {
    "platform": "procore",
    "status": "connected",
    "entities": {
      "projects": 5,
      "customers": 4,
      "contracts": 13,
      "invoices": 8,
      "payments": 8
    }
  }
}

Step 3: Connect Dynamics

curl -X POST "$API_BASE/api/v1/connect" \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer $API_KEY" \
 -d '{"platform": "dynamics"}'
The order is arbitrary - connecting Dynamics first and Procore second produces the same reconciled result.

Step 4: Verify connections

curl "$API_BASE/api/v1/connections" \
 -H "Authorization: Bearer $API_KEY"
{
  "data": {
    "connections": [
      {
        "platform": "procore",
        "status": "active",
        "connected_at": "2026-04-11T12:00:00.000Z",
        "entities_synced": 38
      },
      {
        "platform": "dynamics",
        "status": "active",
        "connected_at": "2026-04-11T12:00:01.000Z",
        "entities_synced": 36
      }
    ]
  }
}

Step 5: Read reconciled data

curl "$API_BASE/api/v1/objects?platform=procore&entity_type=payment" \
 -H "Authorization: Bearer $API_KEY"
Each object in the response has a mappings array. When an entity was reconciled across both platforms, the array contains two entries - one per platform:
{
  "data": [
    {
      "id": "1823456",
      "canonical_id": "pay_xK9mN2vL8gM3y6P",
      "platform": "procore",
      "entity_type": "payment",
      "data": {
        "id": "pay_xK9mN2vL8gM3y6P",
        "object": "payment",
        "amount": { "amount": 170000000, "currency": "USD" },
        "status": "pending",
        "check_number": "CHK-2026-0101",
        "invoice_number": "INV-2025-0061"
      },
      "platform_data": {
        "id": 1823456,
        "amount": "1700000.00",
        "status": "pending",
        "check_number": "CHK-2026-0101"
      },
      "mappings": [
        { "platform": "procore", "platform_id": "1823456" },
        { "platform": "dynamics", "platform_id": "a34e74db-53c7-4368-8fe7-bb87c83c7902" }
      ]
    }
  ]
}
The mappings array proves reconciliation: Procore payment 1823456 and Dynamics payment a34e74db-... are the same real-world payment. You did not have to pair them manually.

Step 6: Clean up

curl -X DELETE "$API_BASE/api/v1/demo/session" \
 -H "Authorization: Bearer $API_KEY"
Returns 204 No Content. The demo customer, API key, and all associated data are deleted.

What’s next