---
id: compound-requests
title: 'Compound Requests'
description: 'A capstone Bulk API example that creates a project hierarchy, invokes an operation on a newly created asset, and queries the result in one request.'
sidebar_label: 'Compound Requests'
sidebar_position: 12
tags: ['api', 'bulk', 'asset', 'examples']
---

The features on the preceding pages compose. This page works through the
suite's capstone example, which creates six assets across five asset types,
invokes an operation on one of them, and queries the outcome — all in a single
round trip.

## Scenario

Automate regression-test setup end to end: create a Scope, a Regression Plan, a
Regression Suite and two Regression Tests, then create a Test Set bound to the
Suite, run `CopyAcceptanceTestsFromRegressionSuite` to generate Tests from the
Regression Tests, and read back what was produced.

## The Request

```yaml title="YAML"
"@scope":
 AssetType: Scope
 Name: Scope for Regression Test
 Parent: Scope:0
 BeginDate: 12/31/2019
---
"@plan":
 AssetType: RegressionPlan
 Name: Plan
 Scope: "@scope"
---
"@suite":
 AssetType: RegressionSuite
 RegressionPlan: "@plan"
 Name: Regression Suite
---
AssetType: RegressionTest
Name: Regression Test 1
Scope: "@scope"
RegressionSuites: "@suite"
---
AssetType: RegressionTest
Name: Regression Test 2
Scope: "@scope"
RegressionSuites: "@suite"
---
"@test-set":
 AssetType: TestSet
 Name: New TestSet
 Scope: "@scope"
 RegressionSuite: "@suite"
---
"@copy":
 from: "@test-set"
 execute: CopyAcceptanceTestsFromRegressionSuite
---
from: "@test-set"
select:
 - Name
 - Scope
 - from: RegressionSuite
   select:
   - RegressionPlan
 - from: Children:Test
   select:
   - Name
   - GeneratedFrom
   - Status
```

```json title="JSON"
[
  {
    "@scope": {
      "AssetType": "Scope", "Name": "Scope for Regression Test",
      "Parent": "Scope:0", "BeginDate": "12/31/2019"
    }
  },
  { "@plan": { "AssetType": "RegressionPlan", "Name": "Plan", "Scope": "@scope" } },
  {
    "@suite": {
      "AssetType": "RegressionSuite", "RegressionPlan": "@plan",
      "Name": "Regression Suite"
    }
  },
  {
    "AssetType": "RegressionTest", "Name": "Regression Test 1",
    "Scope": "@scope", "RegressionSuites": "@suite"
  },
  {
    "AssetType": "RegressionTest", "Name": "Regression Test 2",
    "Scope": "@scope", "RegressionSuites": "@suite"
  },
  {
    "@test-set": {
      "AssetType": "TestSet", "Name": "New TestSet",
      "Scope": "@scope", "RegressionSuite": "@suite"
    }
  },
  { "@copy": { "from": "@test-set", "execute": "CopyAcceptanceTestsFromRegressionSuite" } },
  {
    "from": "@test-set",
    "select": [
      "Name",
      "Scope",
      { "from": "RegressionSuite", "select": ["RegressionPlan"] },
      { "from": "Children:Test", "select": ["Name", "GeneratedFrom", "Status"] }
    ]
  }
]
```

## The Response

```json
{
  "assetsCreated": {
    "oidTokens": [
      "Scope:1533", "RegressionPlan:1534", "RegressionSuite:1535",
      "RegressionTest:1536", "RegressionTest:1537", "TestSet:1538"
    ],
    "count": 6
  },
  "assetsModified": { "oidTokens": [], "count": 0 },
  "assetsOperatedOn": { "oidTokens": ["TestSet:1538"], "count": 1 },
  "commandFailures": { "commands": [], "count": 0 },
  "queryResult": {
    "results": [
      [
        {
          "_oid": "TestSet:1538",
          "Name": "New TestSet",
          "Children:Test": [
            {
              "_oid": "Test:1539",
              "Name": "Regression Test 1",
              "GeneratedFrom": { "_oid": "RegressionTest:1536" },
              "Status": { "_oid": "NULL" }
            },
            {
              "_oid": "Test:1540",
              "Name": "Regression Test 2",
              "GeneratedFrom": { "_oid": "RegressionTest:1537" },
              "Status": { "_oid": "NULL" }
            }
          ]
        }
      ]
    ],
    "count": 1
  }
}
```

## What to Notice

- **Aliases chain.** `@plan` references `@scope`, `@suite` references `@plan`,
  and the Regression Tests and Test Set reference both. None of these assets
  exists when the request is sent.
- **Mixed aliasing is fine.** The two Regression Tests are left unaliased and
  are auto-aliased by the server; nothing else in the request needs to refer
  back to them.
- **`@copy` must be user-aliased.** The operation targets `@test-set`, which
  does not exist at projection time. Aliasing the execute command
  [defers](/apis/asset-bulk/aliases-and-projection#deferring-commands-until-the-processing-phase)
  it to the processing phase.
- **The query needs no alias.** Queries are already evaluated after the
  commands preceding them.
- **`TestSet:1538` appears in both `assetsCreated` and `assetsOperatedOn`,**
  because the request both created it and invoked an operation on it.
- **Assets created by the operation are not in `assetsCreated`.** The two
  generated Tests (`Test:1539`, `Test:1540`) appear only in the query result.
  `assetsCreated` reports assets created by *your* create commands, not
  side effects of an operation.
- **`Status` comes back as `{ "_oid": "NULL" }`,** not `null` — an unset
  single-value relation is an object with the sentinel OID token `NULL`.
- **The downcast key is preserved.** `Children:Test` is both the `from` value
  and the response key.


:::note
An unset single-value relation selects back as `{ "_oid": "NULL" }` — a string
sentinel, not JSON `null`.
:::

## A Smaller Variant

If the Regression Suite and its Regression Tests already exist, the request
collapses to three commands:

```json
[
  {
    "@test-set": {
      "AssetType": "TestSet", "Name": "Tests",
      "Scope": "Scope:1503", "RegressionSuite": "RegressionSuite:1505"
    }
  },
  { "@copy": { "from": "@test-set", "execute": "CopyAcceptanceTestsFromRegressionSuite" } },
  {
    "from": "@test-set",
    "select": [
      "Name",
      { "from": "Children:Test", "select": ["Name", "GeneratedFrom", "Status"] }
    ]
  }
]
```

This is the same pattern — create, defer an operation onto the created asset,
read back — and it is the shape most system-to-system synchronisation code
ends up with.

## Related Topics

- [Projection, processing and aliases](/apis/asset-bulk/aliases-and-projection)
- [Invoking operations](/apis/asset-bulk/operations)
- [Queries](/apis/asset-bulk/queries)
- [cURL examples](/examples/curl)
