Markup
Markup is the main resource of the MarkUp.io API. Create, get, update, and delete markups (MarkUp projects); list and search by workspace; bulk create, move, and delete.
Create Markup from URL
POST /api/v2/markups/url
This URL should lead to webpage or one of supported types .
curl "https://api.markup.io/api/v2/markups/url" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"url": "https://markup.io",
"name": "My Markup"
}'{
"data": {
"id": "411cf862-0b92-43ff-9037-3cd04df06729",
"createdAt": "2026-06-29T11:29:57.950Z",
"modifiedAt": "2026-06-29T11:29:57.950Z",
"type": "webpage",
"name": "MarkUp.io",
"markupUrl": "https://app.markup.io/markup/f289b90a-1166-4f63-aef3-a0cce4543413",
"thumbnailUrl": "https://media.markup.io/thumbnails/markup/9b339cd0-546d-4292-a54b-6e128ce6113e",
"activeThreads": 10,
"readOnly": true,
"status": "editing",
"note": {
"id": "uuid",
"projectId": "uuid",
"note": "Internal note",
"showNoteOnProjectOpen": true
},
"projectReviews": [
{
"projectId": "uuid",
"userId": "uuid",
"comment": "Looks good",
"createdAt": 1705312800000
}
],
"scopes": [
"update-project-read-only",
"delete-project"
],
"url": "https://markup.io"
}
}Response Body - MarkupResponse
Request Body CreateUrlMarkupRequest
| Option | Type | |
|---|---|---|
| url | string | |
| name optional | string | If not set the name will be set to the URL hostname. |
| workspaceId optional | string | If not set or empty, the API key's workspace is used. |
| parentFolderId optional | string | Folder id where the markup will be created. If not set, the workspace root folder is used. |
Create Markup from file(s)
POST /api/v2/markups/file
Create a markup from a file or files in one of supported types .
The endpoint can be used by POST Content-Type: multipart/form-data request with file or files fields. This doesn’t allow uploading files larger than 100MB.
See Create Markup via S3 upload for uploading larger files.
curl "https://api.markup.io/api/v2/markups/file?workspaceId=123e4567-e89b-12d3-a456-426655440000" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: multipart/form-data" \
-F 'file=@/path/to/pictures/picture.jpg'{
"data": {
"id": "b746015f-210f-4756-a727-000ed581e328",
"createdAt": "2026-06-29T11:29:57.950Z",
"modifiedAt": "2026-06-29T11:29:57.950Z",
"type": "webpage",
"name": "MarkUp.io",
"markupUrl": "https://app.markup.io/markup/f289b90a-1166-4f63-aef3-a0cce4543413",
"thumbnailUrl": "https://media.markup.io/thumbnails/markup/9b339cd0-546d-4292-a54b-6e128ce6113e",
"activeThreads": 10,
"readOnly": true,
"status": "editing",
"note": {
"id": "uuid",
"projectId": "uuid",
"note": "Internal note",
"showNoteOnProjectOpen": true
},
"projectReviews": [
{
"projectId": "uuid",
"userId": "uuid",
"comment": "Looks good",
"createdAt": 1705312800000
}
],
"scopes": [
"update-project-read-only",
"delete-project"
],
"url": "https://markup.io"
}
}Response Body - MarkupResponse
Request Query Params CreateFileMarkupRequest
| Option | Type | |
|---|---|---|
| name optional | string | If not set the name will default based on URL or file name. |
| workspaceId | string | |
| parentFolderId optional | string | Folder id where the markup will be created. If not set, the workspace root folder is used. |
Create Markup via S3 upload
POST /api/v2/markups/s3
Create a markup from a file in one of supported types . This endpoint allows uploading files larger than 100MB. The endpoint replies with a presigned S3 URL to which the file should be uploaded. Example of uploading a file to S3 using presigned URL:
curl --upload-file /path/to/file.jpg "<presigned S3 URL>"curl "https://api.markup.io/api/v2/markups/s3?name=My+Markup&workspaceId=89248dda-a130-4de0-9f5d-ceca5e1e8ed7&filesize=123&mimeType=some+mimeType" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" {
"data": {
"url": "https://media-green-markup-io.s3.amazonaws.com/123e4567-e89b-12d3-a456-426655440000?AWSAccessKeyId=AKIAJ2...&Expires=1614787200&Signature=..."
}
}Response Body S3MarkupResponse
| Option | Type | |
|---|---|---|
| url | string |
Request Query Params CreateS3MarkupRequest
| Option | Type | |
|---|---|---|
| name optional | string | If not set the name will default based on URL or file name. |
| workspaceId | string | |
| filesize | number | |
| mimeType | string |
Search Markups
GET /api/v2/markups/search
Search markups in workspace by name or URL (includes subfolders).
curl "https://api.markup.io/api/v2/markups/search?workspaceId=a8552356-c46f-4b0b-80e1-725888ec3d2a" \
-X GET \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" {
"data": {
"data": [
{}
]
}
}Response Body ListMarkupResponse
| Option | Type | |
|---|---|---|
| data | T[] |
Request Query Params SearchMarkupsQuery
| Option | Type | |
|---|---|---|
| workspaceId | string | |
| query optional | string | |
| limit optional | number |
Get Markup
GET /api/v2/markups/:id
curl "https://api.markup.io/api/v2/markups/07b33494-1628-41f9-b957-1c6be055ef82" \
-X GET \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" {
"data": {
"id": "168eba2d-7212-4a4b-a794-feb2a270ba74",
"createdAt": "2026-06-29T11:29:57.950Z",
"modifiedAt": "2026-06-29T11:29:57.950Z",
"type": "webpage",
"name": "MarkUp.io",
"markupUrl": "https://app.markup.io/markup/f289b90a-1166-4f63-aef3-a0cce4543413",
"thumbnailUrl": "https://media.markup.io/thumbnails/markup/9b339cd0-546d-4292-a54b-6e128ce6113e",
"activeThreads": 10,
"readOnly": true,
"status": "editing",
"note": {
"id": "uuid",
"projectId": "uuid",
"note": "Internal note",
"showNoteOnProjectOpen": true
},
"projectReviews": [
{
"projectId": "uuid",
"userId": "uuid",
"comment": "Looks good",
"createdAt": 1705312800000
}
],
"scopes": [
"update-project-read-only",
"delete-project"
],
"url": "https://markup.io"
}
}Response Body - MarkupResponse
Request Path Params IdRequestParam
| Option | Type | |
|---|---|---|
| id | string |
Get Markup Tag
GET /api/v2/markups/:id/tag
Returns taggable and tagged users for the markup (project). Same as v1 GET tag/project/:id.
curl "https://api.markup.io/api/v2/markups/e1f0447b-4ba5-44ce-a474-7b00bbcd8b0d/tag" \
-X GET \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" {
"data": {
"taggable": [
{}
],
"tagged": [
{
"id": "some id",
"name": "some name",
"email": "some email"
}
]
}
}Response Body ProjectMessageTagsResponse
| Option | Type | |
|---|---|---|
| taggable | TaggableTagsResponse[] | |
| tagged | TaggedUserTagResponse[] |
Request Path Params IdRequestParam
| Option | Type | |
|---|---|---|
| id | string |
List Markup View Modes
GET /api/v2/markups/:id/view-modes
Returns the available view modes (device breakpoints) for a markup, with per-mode thread counts.
curl "https://api.markup.io/api/v2/markups/dfe2a5b9-1047-4b15-9b9d-b93b6c3bcabd/view-modes" \
-X GET \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" 204 No ContentRequest Path Params IdRequestParam
| Option | Type | |
|---|---|---|
| id | string |
List All Markups
GET /api/v2/markups
Cursor-based pagination. Use since for next page, before for previous. Order: createdAt desc.
curl "https://api.markup.io/api/v2/markups?workspaceId=9ae13557-38f9-4349-9d7e-e646d87044b3" \
-X GET \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" {
"data": {
"data": [
{}
],
"hasMore": true
}
}Response Body ListMarkupPaginatedResponse
| Option | Type | |
|---|---|---|
| data | ||
| hasMore | boolean | |
| nextCursor | string | |
| prevCursor | string |
Request Query Params ListMarkupsQuery
| Option | Type | |
|---|---|---|
| workspaceId | string | |
| limit optional | number | |
| since optional | string | |
| before optional | string | |
| ttl optional | number |
Update Markup
POST /api/v2/markups/:id
curl "https://api.markup.io/api/v2/markups/37f79315-08b4-4b48-b1c0-add17025e24c" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"name": "MarkUp.io"
}'{
"data": {
"id": "3f12abe8-7eed-478f-8f4a-be422ba3c285",
"createdAt": "2026-06-29T11:29:57.950Z",
"modifiedAt": "2026-06-29T11:29:57.950Z",
"type": "webpage",
"name": "MarkUp.io",
"markupUrl": "https://app.markup.io/markup/f289b90a-1166-4f63-aef3-a0cce4543413",
"thumbnailUrl": "https://media.markup.io/thumbnails/markup/9b339cd0-546d-4292-a54b-6e128ce6113e",
"activeThreads": 10,
"readOnly": true,
"status": "editing",
"note": {
"id": "uuid",
"projectId": "uuid",
"note": "Internal note",
"showNoteOnProjectOpen": true
},
"projectReviews": [
{
"projectId": "uuid",
"userId": "uuid",
"comment": "Looks good",
"createdAt": 1705312800000
}
],
"scopes": [
"update-project-read-only",
"delete-project"
],
"url": "https://markup.io"
}
}Response Body - MarkupResponse
Request Path Params IdRequestParam
| Option | Type | |
|---|---|---|
| id | string |
Request Body UpdateMarkupRequest
| Option | Type | |
|---|---|---|
| name | string |
Pause or Resume New Comments
PATCH /api/v2/markups/:id/read-only
Pauses or resumes new comments on the markup by toggling its readOnly state.
Pausing requires a plan with pauseCommentsEnabled; resuming is always allowed.
curl "https://api.markup.io/api/v2/markups/e7560cb5-0dbe-4826-a6db-00d637d109db/read-only" \
-X PATCH \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"readOnly": true
}'{
"data": {
"id": "e7be8665-62c2-4a14-a7c1-447c6ff21e42",
"createdAt": "2026-06-29T11:29:57.950Z",
"modifiedAt": "2026-06-29T11:29:57.950Z",
"type": "webpage",
"name": "MarkUp.io",
"markupUrl": "https://app.markup.io/markup/f289b90a-1166-4f63-aef3-a0cce4543413",
"thumbnailUrl": "https://media.markup.io/thumbnails/markup/9b339cd0-546d-4292-a54b-6e128ce6113e",
"activeThreads": 10,
"readOnly": true,
"status": "editing",
"note": {
"id": "uuid",
"projectId": "uuid",
"note": "Internal note",
"showNoteOnProjectOpen": true
},
"projectReviews": [
{
"projectId": "uuid",
"userId": "uuid",
"comment": "Looks good",
"createdAt": 1705312800000
}
],
"scopes": [
"update-project-read-only",
"delete-project"
],
"url": "https://markup.io"
}
}Response Body - MarkupResponse
Request Path Params IdRequestParam
| Option | Type | |
|---|---|---|
| id | string |
Request Body UpdateMarkupReadOnlyRequest
| Option | Type | |
|---|---|---|
| readOnly | boolean |
Delete Markup
DELETE /api/v2/markups/:id
curl "https://api.markup.io/api/v2/markups/1d63473b-6c53-4d6f-b0da-deb8590ccba0" \
-X DELETE \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" 204 No ContentRequest Path Params IdRequestParam
| Option | Type | |
|---|---|---|
| id | string |
Bulk Create Markups from URLs
POST /api/v2/markups/bulk/from-url
curl "https://api.markup.io/api/v2/markups/bulk/from-url" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"items": [
{}
]
}'204 No ContentRequest Body BulkCreateMarkupsFromUrlRequest
| Option | Type | |
|---|---|---|
| items | BulkCreateMarkupFromUrlItem[] |
Bulk Create Markups from Files
POST /api/v2/markups/bulk/from-files
curl "https://api.markup.io/api/v2/markups/bulk/from-files" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"items": [
{}
]
}'204 No ContentRequest Body BulkCreateMarkupsFromFilesRequest
| Option | Type | |
|---|---|---|
| items | BulkCreateMarkupFromFileItem[] |
Bulk Move Markups
POST /api/v2/markups/bulk/move
curl "https://api.markup.io/api/v2/markups/bulk/move" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"markupIds": "5578b5e6-2866-4b9d-ac83-00eb92138313",
"targetFolderId": "7128eee4-8af2-4656-aee7-d8dc36d56939"
}'204 No ContentRequest Body BulkMoveMarkupsRequest
| Option | Type | |
|---|---|---|
| markupIds | string[] | |
| targetFolderId | string |
Bulk Delete Markups
POST /api/v2/markups/bulk/delete
curl "https://api.markup.io/api/v2/markups/bulk/delete" \
-X POST \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" \
--data '{
"markupIds": "f0a7631a-0d59-4d1b-adc8-fa0a1286d98c"
}'204 No ContentRequest Body BulkDeleteMarkupsRequest
| Option | Type | |
|---|---|---|
| markupIds | string[] |
Related types
MarkupResponse
| Option | Type | |
|---|---|---|
| MarkupResponse |
WebpageMarkupResponse
| Option | Type | |
|---|---|---|
| id | string | |
| createdAt | Iso8601Timestamp | |
| modifiedAt | Iso8601Timestamp | |
| deletedAt | Iso8601Timestamp | |
| type | ProjectType | |
| name | string | |
| markupUrl | string | |
| thumbnailUrl | string | |
| activeThreads | number | |
| readOnly | boolean | |
| status | ProjectStatus | |
| note | ProjectNoteResponse | |
| projectReviews | ProjectReviewResponse[] | |
| scopes | string[] | |
| url | string |
ImageMarkupResponse
| Option | Type | |
|---|---|---|
| id | string | |
| createdAt | Iso8601Timestamp | |
| modifiedAt | Iso8601Timestamp | |
| deletedAt | Iso8601Timestamp | |
| type | ProjectType | |
| name | string | |
| markupUrl | string | |
| thumbnailUrl | string | |
| activeThreads | number | |
| readOnly | boolean | |
| status | ProjectStatus | |
| note | ProjectNoteResponse | |
| projectReviews | ProjectReviewResponse[] | |
| scopes | string[] | |
| originalMimeType | string | |
| images | MarkupImage[] | |
| isReady | boolean | Some of the files need to be converted before Markup is ready for reviewing.
After the conversion is done, this flag will be set to true and the |
VideoMarkupResponse
| Option | Type | |
|---|---|---|
| id | string | |
| createdAt | Iso8601Timestamp | |
| modifiedAt | Iso8601Timestamp | |
| deletedAt | Iso8601Timestamp | |
| type | ProjectType | |
| name | string | |
| markupUrl | string | |
| thumbnailUrl | string | |
| activeThreads | number | |
| readOnly | boolean | |
| status | ProjectStatus | |
| note | ProjectNoteResponse | |
| projectReviews | ProjectReviewResponse[] | |
| scopes | string[] | |
| video | MarkupVideo | |
| isReady | boolean | Some of the files need to be converted before Markup is ready for reviewing.
After the conversion is done, this flag will be set to true and the |
TaggedUserTagResponse
| Option | Type | |
|---|---|---|
| id | string | |
| name | string | |
| string |