Document Card-related APIs

This commit is contained in:
Stanko K.R.
2025-12-09 16:45:31 +01:00
parent 707bf45063
commit bea8e60fd0
+492 -1
View File
@@ -112,6 +112,92 @@ curl -X PUT \
http://fizzy.localhost:3006/686465299/users/03f5v9zjw7pz8717a4no1h8a7
```
## Rich Text Fields
Some fields accept rich text content. These fields accept HTML input, which will be sanitized to remove unsafe tags and attributes.
```json
{
"card": {
"title": "My card",
"description": "<p>This is <strong>bold</strong> and this is <em>italic</em>.</p><ul><li>Item 1</li><li>Item 2</li></ul>"
}
}
```
### Attaching files to rich text
To attach files (images, documents) to rich text fields, use ActionText's direct upload flow:
#### 1. Create a direct upload
First, request a direct upload URL by sending file metadata:
```bash
curl -X POST \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{
"blob": {
"filename": "screenshot.png",
"byte_size": 12345,
"checksum": "GQ5SqLsM7ylnji0Wgd9wNA==",
"content_type": "image/png"
}
}' \
https://app.fizzy.do/rails/active_storage/direct_uploads
```
The `checksum` is a Base64-encoded MD5 hash of the file content.
__Response:__
```json
{
"id": "abc123",
"key": "abc123def456",
"filename": "screenshot.png",
"content_type": "image/png",
"byte_size": 12345,
"checksum": "GQ5SqLsM7ylnji0Wgd9wNA==",
"direct_upload": {
"url": "https://storage.example.com/...",
"headers": {
"Content-Type": "image/png",
"Content-MD5": "GQ5SqLsM7ylnji0Wgd9wNA=="
}
},
"signed_id": "eyJfcmFpbHMi..."
}
```
#### 2. Upload the file
Upload the file directly to the provided URL with the specified headers:
```bash
curl -X PUT \
-H "Content-Type: image/png" \
-H "Content-MD5: GQ5SqLsM7ylnji0Wgd9wNA==" \
--data-binary @screenshot.png \
"https://storage.example.com/..."
```
#### 3. Reference the file in rich text
Use the `signed_id` from step 1 to embed the file in your rich text using an `<action-text-attachment>` tag:
```json
{
"card": {
"title": "Card with image",
"description": "<p>Here's a screenshot:</p><action-text-attachment sgid=\"eyJfcmFpbHMi...\"></action-text-attachment>"
}
}
```
The `sgid` attribute should contain the `signed_id` returned from the direct upload response.
## Endpoints
### Identity
@@ -288,7 +374,412 @@ Returns `204 No Content` on success.
### Cards
Cards are tasks or items of work on a board
Cards are tasks or items of work on a board. They can be organized into columns, tagged, assigned to users, and have comments.
#### `GET /:account_slug/cards`
Returns a paginated list of cards you have access to. Results can be filtered using query parameters.
__Query Parameters:__
| Parameter | Description |
|-----------|-------------|
| `board_id` | Filter by board ID |
| `column_id` | Filter by column ID |
| `tag_id` | Filter by tag ID |
| `assignee_id` | Filter by assignee user ID |
| `status` | Filter by status: `published`, `closed`, `not_now` |
__Response:__
```json
[
{
"id": "03f5vaeq985jlvwv3arl4srq2",
"number": 1,
"title": "First!",
"status": "published",
"description": "Hello, World!",
"description_html": "<div class=\"action-text-content\"><p>Hello, World!</p></div>",
"image_url": null,
"tags": ["programming"],
"golden": false,
"last_active_at": "2025-12-05T19:38:48.553Z",
"created_at": "2025-12-05T19:38:48.540Z",
"url": "http://fizzy.localhost:3006/897362094/cards/4",
"board": {
"id": "03f5v9zkft4hj9qq0lsn9ohcm",
"name": "Fizzy",
"all_access": true,
"created_at": "2025-12-05T19:36:35.534Z",
"url": "http://fizzy.localhost:3006/897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm",
"creator": {
"id": "03f5v9zjw7pz8717a4no1h8a7",
"name": "David Heinemeier Hansson",
"role": "owner",
"active": true,
"email_address": "david@example.com",
"created_at": "2025-12-05T19:36:35.401Z",
"url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7"
}
},
"creator": {
"id": "03f5v9zjw7pz8717a4no1h8a7",
"name": "David Heinemeier Hansson",
"role": "owner",
"active": true,
"email_address": "david@example.com",
"created_at": "2025-12-05T19:36:35.401Z",
"url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7"
},
"comments_url": "http://fizzy.localhost:3006/897362094/cards/4/comments"
},
]
```
#### `GET /:account_slug/cards/:card_number`
Returns a specific card by its number.
__Response:__
Same as the card object in the list response.
#### `POST /:account_slug/boards/:board_id/cards`
Creates a new card in a board.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `title` | string | Yes | The title of the card |
| `description` | string | No | Rich text description of the card |
| `status` | string | No | Initial status: `published` (default), `closed`, `not_now` |
| `image` | file | No | Header image for the card |
| `tag_ids` | array | No | Array of tag IDs to apply to the card |
__Request:__
```json
{
"card": {
"title": "Add dark mode support",
"description": "We need to add dark mode to the app"
}
}
```
__Response:__
Returns `201 Created` with a `Location` header pointing to the new card.
#### `PUT /:account_slug/cards/:card_number`
Updates a card.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `title` | string | No | The title of the card |
| `description` | string | No | Rich text description of the card |
| `status` | string | No | Card status: `published`, `closed`, `not_now` |
| `image` | file | No | Header image for the card |
| `tag_ids` | array | No | Array of tag IDs to apply to the card |
__Request:__
```json
{
"card": {
"title": "Add dark mode support (Updated)"
}
}
```
__Response:__
Returns the updated card.
#### `DELETE /:account_slug/cards/:card_number`
Deletes a card. Only the card creator or board administrators can delete cards.
__Response:__
Returns `204 No Content` on success.
#### `POST /:account_slug/cards/:card_number/closure`
Closes a card.
__Response:__
Returns `204 No Content` on success.
#### `DELETE /:account_slug/cards/:card_number/closure`
Reopens a closed card.
__Response:__
Returns `204 No Content` on success.
#### `POST /:account_slug/cards/:card_number/not_now`
Moves a card to "Not Now" status.
__Response:__
Returns `204 No Content` on success.
#### `POST /:account_slug/cards/:card_number/triage`
Moves a card from triage into a column.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `column_id` | string | Yes | The ID of the column to move the card into |
__Response:__
Returns `204 No Content` on success.
#### `DELETE /:account_slug/cards/:card_number/triage`
Sends a card back to triage.
__Response:__
Returns `204 No Content` on success.
#### `POST /:account_slug/cards/:card_number/taggings`
Toggles a tag on or off for a card. If the tag doesn't exist, it will be created.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `tag_title` | string | Yes | The title of the tag (leading `#` is stripped) |
__Response:__
Returns `204 No Content` on success.
#### `POST /:account_slug/cards/:card_number/assignments`
Toggles assignment of a user to/from a card.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `assignee_id` | string | Yes | The ID of the user to assign/unassign |
__Response:__
Returns `204 No Content` on success.
#### `POST /:account_slug/cards/:card_number/watch`
Subscribes the current user to notifications for this card.
__Response:__
Returns `204 No Content` on success.
#### `DELETE /:account_slug/cards/:card_number/watch`
Unsubscribes the current user from notifications for this card.
__Response:__
Returns `204 No Content` on success.
### Comments
Comments are attached to cards and support rich text.
#### `GET /:account_slug/cards/:card_number/comments/:comment_id`
Returns a specific comment.
__Response:__
```json
{
"id": "03f5v9zo9qlcwwpyc0ascnikz",
"created_at": "2025-12-05T19:36:35.534Z",
"updated_at": "2025-12-05T19:36:35.534Z",
"body": {
"plain_text": "This looks great!",
"html": "<div class=\"action-text-content\">This looks great!</div>"
},
"creator": {
"id": "03f5v9zjw7pz8717a4no1h8a7",
"name": "David Heinemeier Hansson",
"role": "owner",
"active": true,
"email_address": "david@example.com",
"created_at": "2025-12-05T19:36:35.401Z",
"url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7"
},
"reactions_url": "http://fizzy.localhost:3006/897362094/cards/3/comments/03f5v9zo9qlcwwpyc0ascnikz/reactions",
"url": "http://fizzy.localhost:3006/897362094/cards/3/comments/03f5v9zo9qlcwwpyc0ascnikz"
}
```
#### `POST /:account_slug/cards/:card_number/comments`
Creates a new comment on a card.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `body` | string | Yes | The comment body (supports rich text) |
__Request:__
```json
{
"comment": {
"body": "This looks great!"
}
}
```
__Response:__
Returns `201 Created` with a `Location` header pointing to the new comment.
#### `PUT /:account_slug/cards/:card_number/comments/:comment_id`
Updates a comment. Only the comment creator can update their comments.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `body` | string | Yes | The updated comment body |
__Request:__
```json
{
"comment": {
"body": "This looks even better now!"
}
}
```
__Response:__
Returns the updated comment.
#### `DELETE /:account_slug/cards/:card_number/comments/:comment_id`
Deletes a comment. Only the comment creator can delete their comments.
__Response:__
Returns `204 No Content` on success.
### Reactions
Reactions are short - 16 character long - responses to comments.
#### `POST /:account_slug/cards/:card_number/comments/:comment_id/reactions`
Adds a reaction to a comment.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `content` | string | Yes | The reaction emoji (e.g., "👍", "❤️", "🎉") |
__Request:__
```json
{
"reaction": {
"content": "👍"
}
}
```
__Response:__
Returns `201 Created` on success.
#### `DELETE /:account_slug/cards/:card_number/comments/:comment_id/reactions/:reaction_id`
Removes your reaction from a comment.
__Response:__
Returns `204 No Content` on success.
### Steps
Steps are to-do items on a card.
#### `GET /:account_slug/cards/:card_number/steps/:step_id`
Returns a specific step.
__Response:__
```json
{
"id": "03f5v9zo9qlcwwpyc0ascnikz",
"content": "Write tests",
"completed": false
}
```
#### `POST /:account_slug/cards/:card_number/steps`
Creates a new step on a card.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `content` | string | Yes | The step text |
| `completed` | boolean | No | Whether the step is completed (default: `false`) |
__Request:__
```json
{
"step": {
"content": "Write tests"
}
}
```
__Response:__
Returns `201 Created` with a `Location` header pointing to the new step.
#### `PUT /:account_slug/cards/:card_number/steps/:step_id`
Updates a step.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `content` | string | No | The step text |
| `completed` | boolean | No | Whether the step is completed |
__Request:__
```json
{
"step": {
"completed": true
}
}
```
__Response:__
Returns the updated step.
#### `DELETE /:account_slug/cards/:card_number/steps/:step_id`
Deletes a step.
__Response:__
Returns `204 No Content` on success.
### Columns