---
title: "Create up to 100 cards in one transaction"
method: POST
path: "/projects/{id}/cards/bulk"
---

# Create up to 100 cards in one transaction

`POST /projects/{id}/cards/bulk`

## Request

- Base URL: `https://craaft.io/api/v1`
- URL: `https://craaft.io/api/v1/projects/{id}/cards/bulk`
- Auth: HTTP bearer

All-or-nothing batch create - one invalid item rolls back the whole
batch and the error names the offending index (`cards[3]: …`).
Cards without an explicit `position` append to the end of their
column in request order. Unlike the single-card create, the
assignee is NOT defaulted to the caller. Bulk requests never send
notification emails; activity events and SSE broadcasts fire
normally. Body limit 1 MiB.

## Request body

- object
  - `cards` object[], required
    - `title` string, required
    - `column` string, required: column.key
    - `description` string
    - `position` number: Omit to append to the end of the column
    - `dueDate` string, date-time
    - `assignedUserId` string, uuid
    - `size` integer
    - `priority` 'low' | 'medium' | 'high' | 'urgent'
    - `tags` string[]

## Response `201`

Created cards, in request order

- BulkCardsResponse
  - `cards` Card[], required: Affected cards, in request order
    - `id` string, uuid, required
    - `projectId` string, uuid, required
    - `column` string, required
    - `title` string, required
    - `description` string: Full body on GET /cards/{id}, PATCH, create, and /detail. Omitted from GET /projects/{id}/cards and lean SSE card.updated events (position-only moves).
    - `position` number, required
    - `dueDate` string, date-time, nullable
    - `assignedUserId` string, uuid, nullable
    - `assignedUserName` string, nullable
    - `size` integer, nullable: Optional integer size estimate; null when unset
    - `priority` 'low' | 'medium' | 'high' | 'urgent' | 'null', nullable
    - `createdBy` string, uuid, nullable
    - `createdByName` string, nullable
    - `updatedBy` string, uuid, nullable
    - `updatedByName` string, nullable
    - `attachmentCount` integer
    - `checklistDone` integer: Completed checklist items (denormalized count)
    - `checklistTotal` integer: Total checklist items (denormalized count)
    - `tags` string[]
    - `following` boolean: Whether the authenticated caller follows this card
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required

## Other responses

- `400`: Invalid item (message names the index), too many items, or invalid column/assignee
- `404`: Resource doesn't exist or caller isn't a member of its workspace

---

[API](https://skmtc.dev/craaft/apis/craaft-api.md) · [All operations](https://skmtc.dev/craaft/apis/craaft-api/llms.txt) · [OpenAPI document](https://skmtc.dev/craaft/apis/craaft-api/revisions/3a1e9d30d7dc?raw)
