Files
fizzy/docs/API.md
T
2025-12-10 09:23:52 +01:00

26 KiB

Fizzy API

Fizzy has an API that allows you to integrate your application with it or to create a bot to perform various actions for you.

Authentication

To use the API you'll need an access token. To get one, go to your profile, then, in the API section, click on "Personal access tokens" and then click on "Generate new access token".

Give it a description and pick what kind of permission you want the access token to have:

  • Read: allows reading data from your account
  • Read + Write: allows reading and writing data to your account on your behalf

Then click on "Generate access token".

Access token generation guide with screenshots
Step Description Screenshot
1 Go to your profile Profile page with API section
2 In the API section click on "Personal access token" Personal access tokens page
3 Click on "Generate a new access token" Generate new access token dialog
4 Give it a description and assign it a permission Access token created

Important

An access token is like a password, keep it secret and do not share it with anyone. Any person or application that has your access token can perform actions on your behalf.

To authenticate a request using your access token, include it in the Authorization header:

curl -H "Authorization: Bearer put-your-access-token-here" -H "Accept: application/json" https://app.fizzy.do/identity

Caching

Most endpoints return ETag and Cache-Control headers. You can use these to avoid re-downloading unchanged data.

Using ETags

When you make a request, the response includes an ETag header:

HTTP/1.1 200 OK
ETag: "abc123"
Cache-Control: max-age=0, private, must-revalidate

On subsequent requests, include the ETag value in the If-None-Match header:

GET /1234567/cards/42.json
If-None-Match: "abc123"

If the resource hasn't changed, you'll receive a 304 Not Modified response with no body, saving bandwidth and processing time:

HTTP/1.1 304 Not Modified
ETag: "abc123"

If the resource has changed, you'll receive the full response with a new ETag.

Example in Ruby:

# Store the ETag from the response
etag = response.headers["ETag"]

# On next request, send it back
headers = { "If-None-Match" => etag }
response = client.get("/1234567/cards/42.json", headers: headers)

if response.status == 304
  # Nothing to do, the card hasn't changed
else
  # The card has changed, process the new data
end

Pagination

All endpoints that return a list of items are paginated. The page size can vary from endpoint to endpoint, and we use a dynamic page size where initial pages return fewer results than later pages.

If there are more results to fetch, the response will include a Link header with a rel="next" link to the next page of results:

curl -H "Authorization: Bearer put-your-access-token-here" -H "Accept: application/json" -v http://fizzy.localhost:3006/686465299/cards
# ...
< link: <http://fizzy.localhost:3006/686465299/cards?page=2>; rel="next"
# ...

File Uploads

Some endpoints accept file uploads. To upload a file, send a multipart/form-data request instead of JSON. You can combine file uploads with other parameters in the same request.

Example using curl:

curl -X PUT \
  -H "Authorization: Bearer put-your-access-token-here" \
  -F "user[name]=David H. Hansson" \
  -F "user[avatar]=@/path/to/avatar.jpg" \
  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.

{
  "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:

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:

{
  "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:

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:

{
  "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

An Identity represents a person using Fizzy, their email address and their users in different accounts.

GET /identity

Returns a list of accounts, including the User, the Identity has access to

{
  "accounts": [
    {
      "id": "03f5v9zjskhcii2r45ih3u1rq",
      "name": "37signals",
      "slug": "/897362094",
      "created_at": "2025-12-05T19:36:35.377Z",
      "user": {
        "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/users/03f5v9zjw7pz8717a4no1h8a7"
      }
    },
    {
      "id": "03f5v9zpko7mmhjzwum3youpp",
      "name": "Honcho",
      "slug": "/686465299",
      "created_at": "2025-12-05T19:36:36.746Z",
      "user": {
        "id": "03f5v9zppzlksuj4mxba2nbzn",
        "name": "David Heinemeier Hansson",
        "role": "owner",
        "active": true,
        "email_address": "david@example.com",
        "created_at": "2025-12-05T19:36:36.783Z",
        "url": "http://fizzy.localhost:3006/users/03f5v9zppzlksuj4mxba2nbzn"
      }
    }
  ]
}

Boards

Boards are where you organize your work - they contain your cards.

GET /:account_slug/boards

Returns a list of Boards, that you can access, in the specified account.

Response:

[
  {
    "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"
    }
  }
]

GET /:account_slug/boards/:board_id

Returns the specific Board.

Response:

{
  "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"
  }
}

POST /:account_slug/boards

Creates a new Board in the account.

Parameter Type Required Description
name string Yes The name of the board
all_access boolean No Whether any user in the account can access this board. Defaults to true
auto_postpone_period integer No Number of days of inactivity before cards are automatically postponed
public_description string No Rich text description shown on the public board page

Request:

{
  "board": {
    "name": "My new board",
  }
}

Response:

Returns 201 Created with a Location header pointing to the new board:

HTTP/1.1 201 Created
Location: /897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm.json

PUT /:account_slug/boards/:board_id

Updates a Board. Only board administrators can update a board.

Parameter Type Required Description
name string No The name of the board
all_access boolean No Whether any user in the account can access this board
auto_postpone_period integer No Number of days of inactivity before cards are automatically postponed
public_description string No Rich text description shown on the public board page
user_ids array No Array of all user IDs who should have access to this board (only applicable when all_access is false)

Request:

{
  "board": {
    "name": "Updated board name",
    "auto_postpone_period": 14,
    "public_description": "This is a **public** description of the board.",
    all_access: false,
    "user_ids": [
      "03f5v9zppzlksuj4mxba2nbzn",
      "03f5v9zjw7pz8717a4no1h8a7"
    ]
  }
}

Response:

Returns 204 No Content on success.

DELETE /:account_slug/boards/:board_id

Deletes a Board. Only board administrators can delete a board.

Response:

Returns 204 No Content on success.

Cards

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:

[
  {
    "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

{
  "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

Columns represent stages in a workflow on a board. Cards move through columns as they progress.

GET /:account_slug/boards/:board_id/columns/:column_id

Returns the specified column.

Response:

{
  "id": "03f5v9zkft4hj9qq0lsn9ohcm",
  "name": "In Progress",
  "color": "var(--color-card-default)",
  "created_at": "2025-12-05T19:36:35.534Z"
}

POST /:account_slug/boards/:board_id/columns

Creates a new column on the board.

Parameter Type Required Description
name string Yes The name of the column
color string No The column color. One of: var(--color-card-default) (Blue), var(--color-card-1) (Gray), var(--color-card-2) (Tan), var(--color-card-3) (Yellow), var(--color-card-4) (Lime), var(--color-card-5) (Aqua), var(--color-card-6) (Violet), var(--color-card-7) (Purple), var(--color-card-8) (Pink)

Request:

{
  "column": {
    "name": "In Progress",
    "color": "var(--color-card-4)"
  }
}

Response:

Returns 201 Created with a Location header pointing to the new column.

PUT /:account_slug/boards/:board_id/columns/:column_id

Updates a column.

Parameter Type Required Description
name string No The name of the column
color string No The column color

Request:

{
  "column": {
    "name": "Done"
  }
}

Response:

Returns 204 No Content on success.

DELETE /:account_slug/boards/:board_id/columns/:column_id

Deletes a column.

Response:

Returns 204 No Content on success.

Users

Users represent people who have access to an account.

GET /:account_slug/users

Returns a list of active users in the account.

Response:

[
  {
    "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"
  },
  {
    "id": "03f5v9zjysoy0fqs9yg0ei3hq",
    "name": "Jason Fried",
    "role": "member",
    "active": true,
    "email_address": "jason@example.com",
    "created_at": "2025-12-05T19:36:35.419Z",
    "url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjysoy0fqs9yg0ei3hq"
  },
  {
    "id": "03f5v9zk1dtqduod5bkhv3k8m",
    "name": "Jason Zimdars",
    "role": "member",
    "active": true,
    "email_address": "jz@example.com",
    "created_at": "2025-12-05T19:36:35.435Z",
    "url": "http://fizzy.localhost:3006/897362094/users/03f5v9zk1dtqduod5bkhv3k8m"
  },
  {
    "id": "03f5v9zk3nw9ja92e7s4h2wbe",
    "name": "Kevin Mcconnell",
    "role": "member",
    "active": true,
    "email_address": "kevin@example.com",
    "created_at": "2025-12-05T19:36:35.451Z",
    "url": "http://fizzy.localhost:3006/897362094/users/03f5v9zk3nw9ja92e7s4h2wbe"
  }
]

GET /:account_slug/users/:user_id

Returns the specified user.

Response:

{
  "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"
}

PUT /:account_slug/users/:user_id

Updates a user. You can only update users you have permission to change.

Parameter Type Required Description
name string No The user's display name
avatar file No The user's avatar image

Request:

{
  "user": {
    "name": "David H. Hansson"
  }
}

Response:

Returns 204 No Content on success.

DELETE /:account_slug/users/:user_id

Deactivates a user. You can only deactivate users you have permission to change.

Response:

Returns 204 No Content on success.

Notifications

Notifications inform users about events that happened in the account, such as comments, assignments, and card updates.

GET /:account_slug/notifications

Returns a list of notifications for the current user. Unread notifications are returned first, followed by read notifications.

Response:

[
  {
    "id": "03f5va03bpuvkcjemcxl73ho2",
    "read": false,
    "read_at": null,
    "created_at": "2025-11-19T04:03:58.000Z",
    "title": "Plain text mentions",
    "body": "Assigned to self",
    "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"
    },
    "card": {
      "id": "03f5v9zo9qlcwwpyc0ascnikz",
      "title": "Plain text mentions",
      "status": "published",
      "url": "http://fizzy.localhost:3006/897362094/cards/3"
    },
    "url": "http://fizzy.localhost:3006/897362094/notifications/03f5va03bpuvkcjemcxl73ho2"
  }
]

POST /:account_slug/notifications/:notification_id/reading

Marks a notification as read.

Response:

Returns 204 No Content on success.

DELETE /:account_slug/notifications/:notification_id/reading

Marks a notification as unread.

Response:

Returns 204 No Content on success.

POST /:account_slug/notifications/bulk_reading

Marks all unread notifications as read.

Response:

Returns 204 No Content on success.