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": "f028822b-90d0-4dca-8123-d40578041694",
"createdAt": "2026-06-11T11:43:35.938Z",
"modifiedAt": "2026-06-11T11:43:35.938Z",
"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": "719f015d-9d92-4905-8d2c-325eb10ff071",
"createdAt": "2026-06-11T11:43:35.938Z",
"modifiedAt": "2026-06-11T11:43:35.938Z",
"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=4b3408b4-eae8-47b4-8d2c-8cb59bd8b468&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=1efa88a0-9de0-494f-ad35-8383013000a1" \
-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/93628a96-c308-4095-b1ca-0e7b19362244" \
-X GET \
-H "Authorization: Bearer <API-KEY-SECRET>" \
-H "Markup-API-Version: 2023-02-22" \
-H "Content-Type: application/json" {
"data": {
"id": "14c4dd62-5ba7-40fa-b12f-445b74ad7224",
"createdAt": "2026-06-11T11:43:35.938Z",
"modifiedAt": "2026-06-11T11:43:35.938Z",
"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/49fa79ee-b26d-4fe0-aead-8185fb12c349/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/c37d05b9-7e04-40a7-8eea-3e06f6434d06/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=0349ed0b-54fd-4032-b456-9c70dac56f2b" \
-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/e6a3b41b-452c-44e1-bc5a-b1bd7e58ea17" \
-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": "af283106-867a-4191-8593-38f65462565a",
"createdAt": "2026-06-11T11:43:35.938Z",
"modifiedAt": "2026-06-11T11:43:35.938Z",
"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/10b7cc54-003e-4fc7-a0fb-31fa50d986cb/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": "cf6cbdde-9be1-4df2-bc70-dafb80b74b6d",
"createdAt": "2026-06-11T11:43:35.938Z",
"modifiedAt": "2026-06-11T11:43:35.938Z",
"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/f97dd6a2-b842-4b3e-a827-9819d0f16d9a" \
-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": "7ef70e61-d5ab-4d96-9299-9d134379448e",
"targetFolderId": "ccc54cc6-2b82-4004-840a-c696d95dac5f"
}'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": "9d2a7304-846d-4795-9577-769ec3599dee"
}'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 |