# Bulk operations

Source: https://ceyo.ai/docs/signal/bulk-operations

### Bulk operations

Poll asynchronous project and location creation and inspect the result of every submitted record.

### Get bulk operation

`GET /bulk-operations/{id}`

Returns the current state and item results for one bulk create operation.

#### Path parameters

| Name | Type | Details | Description |
| --- | --- | --- | --- |
| `id` | uuid | Required | Bulk operation identifier returned by a bulk create request. |

#### BulkOperation response envelope

`id`:**uuid**`type`:**projects | locations**`status`:**pending | running | completed | completed\_with\_errors | failed**`parent_project_id`:**uuid | null**`total`:**integer**`pending`:**integer**`succeeded`:**integer**`failed`:**integer**`status_url`:**string**`items`:**BulkOperationItem\[\]**

| Name | Type | Details | Description |
| --- | --- | --- | --- |
| `id` | uuid |  | Bulk operation identifier. |
| `type` | projects \| locations |  | Resource type created by the operation. |
| `status` | pending \| running \| completed \| completed\_with\_errors \| failed |  | Current operation state. |
| `parent_project_id` | uuid \| null |  | Parent project for a location operation; null for a project operation. |
| `total` | integer |  | Submitted record count. |
| `pending` | integer |  | Records that have not reached a terminal state. |
| `succeeded` | integer |  | Records created successfully. |
| `failed` | integer |  | Records that failed validation or processing. |
| `status_url` | string |  | Relative URL for polling this operation. |
| `items` | BulkOperationItem\[\] |  | One result for each submitted record, ordered by input index. |

#### BulkOperationItem

| Name | Type | Details | Description |
| --- | --- | --- | --- |
| `index` | integer |  | Zero-based position in the submitted array. |
| `status` | pending \| queued \| running \| succeeded \| failed |  | Current item state. |
| `resource_id` | uuid |  | Created project or location identifier when successful. |
| `external_id` | string \| null |  | Partner identifier copied from the created resource. |
| `onboarding_started` | boolean |  | Whether this item created an onboarding run from start: true. |
| `onboarding_operation` | OnboardingOperation |  | Onboarding status and polling URL when onboarding\_started is true. |
| `error` | object |  | Stable error code, message, and field details for a failed item. |

> **Polling**
>
> Poll the returned `status_url` until the operation is `completed`, `completed_with_errors`, or `failed`. Item failures do not roll back successful records.

> **Safe errors**
>
> Item errors contain stable public codes and sanitized field details. Unexpected internal failures return `processing_failed` without provider names, exception messages, or implementation details.

#### Request and response

```curl
curl --request GET \
  --url 'https://api.signal.ceyo.ai/v1/bulk-operations/f9bc15cc-e9c9-4e93-a93e-b713c92c7315' \
  --header 'Authorization: Bearer ceyo_platform_...'
```

```json
{
  "bulk_operation": {
    "id": "f9bc15cc-e9c9-4e93-a93e-b713c92c7315",
    "type": "projects",
    "status": "completed_with_errors",
    "parent_project_id": null,
    "total": 2,
    "pending": 0,
    "succeeded": 1,
    "failed": 1,
    "created_at": "2026-08-04T15:00:00Z",
    "started_at": "2026-08-04T15:00:01Z",
    "completed_at": "2026-08-04T15:00:03Z",
    "status_url": "/v1/bulk-operations/f9bc15cc-e9c9-4e93-a93e-b713c92c7315",
    "items": [
      {
        "index": 0,
        "status": "succeeded",
        "resource_id": "e6c96c98-d777-40e0-94ec-48931f57782f",
        "external_id": "partner-project-acme",
        "onboarding_started": true,
        "onboarding_operation": {
          "id": "1c07ea43-a8fe-4d07-8741-9c624d67b466",
          "status": "queued",
          "resource_type": "project",
          "resource_id": "e6c96c98-d777-40e0-94ec-48931f57782f",
          "progress": {
            "completed": 0,
            "total": 6
          },
          "message": "Onboarding is queued.",
          "steps": [
            {
              "key": "enrichment",
              "status": "pending"
            },
            {
              "key": "topics",
              "status": "pending"
            },
            {
              "key": "prompts",
              "status": "pending"
            },
            {
              "key": "competitors",
              "status": "pending"
            },
            {
              "key": "visibility",
              "status": "pending"
            },
            {
              "key": "diagnosis",
              "status": "pending"
            }
          ],
          "status_url": "/v1/onboarding-operations/1c07ea43-a8fe-4d07-8741-9c624d67b466"
        },
        "started_at": "2026-08-04T15:00:01Z",
        "completed_at": "2026-08-04T15:00:02Z"
      },
      {
        "index": 1,
        "status": "failed",
        "error": {
          "code": "validation_failed",
          "message": "The record failed validation.",
          "details": [
            {
              "field": "package_id",
              "message": "is invalid"
            }
          ]
        },
        "started_at": "2026-08-04T15:00:01Z",
        "completed_at": "2026-08-04T15:00:03Z"
      }
    ]
  }
}
```

#### Errors

#### Error response envelope

| Name | Type | Details | Description |
| --- | --- | --- | --- |
| `error` | Error |  | Structured error payload. |

#### Error

| Name | Type | Details | Description |
| --- | --- | --- | --- |
| `code` | string |  | Stable snake\_case code suitable for programmatic handling. |
| `message` | string |  | Human-readable explanation of the failure. |
| `details` | object \| array \| null |  | Structured validation or request context when available. |
| `request_id` | string |  | Identifier to provide when requesting support. |

```json
{
  "error": {
    "code": "validation_failed",
    "message": "One or more fields are invalid.",
    "details": [
      {
        "field": "name",
        "message": "must be present"
      }
    ],
    "request_id": "req_01K1GP6J8QQFZ4D2B6C5A9V3TS"
  }
}
```

#### Status codes

| Name | Type | Details | Description |
| --- | --- | --- | --- |
| `401` | invalid\_api\_key |  | The API key is absent, invalid, expired, or revoked. |
| `404` | bulk\_operation\_not\_found |  | The operation does not exist or is outside the API key scope. |
