WorkscopeAPI Open Workscope

API reference

Clients

15 requests. Each shows the permission a key needs, what to send and what comes back.

On this page

Clients

GET/v1/clients

Permission
client.view
Answers
200

Parameters

NameInKind
statusqueryenumOne of live, archived
qquerystring
tagqueryenumOne of all, active, past, prospect, none

Response array of object

  • iduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • websitestringrequiredcan be null
  • addressstringrequiredcan be null
  • notesstringrequiredcan be null
  • logoUrlstringrequiredcan be null
  • statusenumrequired

    One of "live", "archived"

  • isInternalbooleanrequired
  • customFieldsobjectrequired
  • tagsarray of enumrequired
  • createdAtstringrequired
curl "https://app.workscope.co.uk/v1/clients" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

[
  {
    "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
    "name": "Harbourside Dental",
    "email": "office@example.co.uk",
    "phone": "0117 496 0123",
    "website": "https://example.co.uk",
    "address": "1 Harbour Road, Bristol",
    "notes": "Side gate code is on the key safe.",
    "logoUrl": "https://example.co.uk",
    "status": "live",
    "isInternal": false,
    "customFields": {
      "contract-number": "CN-1042"
    },
    "tags": [
      "prospect"
    ],
    "createdAt": "2026-11-06T09:30:00.000Z"
  }
]

Add a client

POST/v1/clients

Permission
client.manage
Answers
201

Request body JSON

  • namestringrequired

    1–200 characters

  • emailconstant or stringoptionalcan be null
  • phonestringoptionalcan be null

    Up to 50 characters

  • websitestringoptionalcan be null

    Up to 300 characters

  • addressstringoptionalcan be null

    Up to 1000 characters

  • notesstringoptionalcan be null

    Up to 5000 characters

  • customFieldsobjectoptional

Response object

  • iduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • websitestringrequiredcan be null
  • addressstringrequiredcan be null
  • notesstringrequiredcan be null
  • logoUrlstringrequiredcan be null
  • statusenumrequired

    One of "live", "archived"

  • isInternalbooleanrequired
  • customFieldsobjectrequired
  • tagsarray of enumrequired
  • createdAtstringrequired
curl -X POST "https://app.workscope.co.uk/v1/clients" \
  -H "Authorization: Bearer wsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Harbourside Dental",
    "email": "",
    "phone": "0117 496 0123",
    "website": "https://example.co.uk",
    "address": "1 Harbour Road, Bristol",
    "notes": "Side gate code is on the key safe.",
    "customFields": {
      "contract-number": "CN-1042"
    }
  }'

Example response

{
  "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
  "name": "Harbourside Dental",
  "email": "office@example.co.uk",
  "phone": "0117 496 0123",
  "website": "https://example.co.uk",
  "address": "1 Harbour Road, Bristol",
  "notes": "Side gate code is on the key safe.",
  "logoUrl": "https://example.co.uk",
  "status": "live",
  "isInternal": false,
  "customFields": {
    "contract-number": "CN-1042"
  },
  "tags": [
    "prospect"
  ],
  "createdAt": "2026-11-06T09:30:00.000Z"
}

One client

GET/v1/clients/{id}

Permission
client.view
Answers
200

Parameters

NameInKind
idpathuuidrequired

Response object

  • iduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • websitestringrequiredcan be null
  • addressstringrequiredcan be null
  • notesstringrequiredcan be null
  • logoUrlstringrequiredcan be null
  • statusenumrequired

    One of "live", "archived"

  • isInternalbooleanrequired
  • customFieldsobjectrequired
  • tagsarray of enumrequired
  • createdAtstringrequired
curl "https://app.workscope.co.uk/v1/clients/ID" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

{
  "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
  "name": "Harbourside Dental",
  "email": "office@example.co.uk",
  "phone": "0117 496 0123",
  "website": "https://example.co.uk",
  "address": "1 Harbour Road, Bristol",
  "notes": "Side gate code is on the key safe.",
  "logoUrl": "https://example.co.uk",
  "status": "live",
  "isInternal": false,
  "customFields": {
    "contract-number": "CN-1042"
  },
  "tags": [
    "prospect"
  ],
  "createdAt": "2026-11-06T09:30:00.000Z"
}

Change or archive a client

PATCH/v1/clients/{id}

Permission
client.manage
Answers
200

Parameters

NameInKind
idpathuuidrequired

Request body JSON

  • namestringoptional

    1–200 characters

  • emailconstant or stringoptionalcan be null
  • phonestringoptionalcan be null

    Up to 50 characters

  • websitestringoptionalcan be null

    Up to 300 characters

  • addressstringoptionalcan be null

    Up to 1000 characters

  • notesstringoptionalcan be null

    Up to 5000 characters

  • customFieldsobjectoptional
  • statusenumoptional

    One of "live", "archived"

Response object

  • iduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • websitestringrequiredcan be null
  • addressstringrequiredcan be null
  • notesstringrequiredcan be null
  • logoUrlstringrequiredcan be null
  • statusenumrequired

    One of "live", "archived"

  • isInternalbooleanrequired
  • customFieldsobjectrequired
  • tagsarray of enumrequired
  • createdAtstringrequired
curl -X PATCH "https://app.workscope.co.uk/v1/clients/ID" \
  -H "Authorization: Bearer wsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Harbourside Dental",
    "email": "",
    "phone": "0117 496 0123",
    "website": "https://example.co.uk",
    "address": "1 Harbour Road, Bristol",
    "notes": "Side gate code is on the key safe.",
    "customFields": {
      "contract-number": "CN-1042"
    },
    "status": "live"
  }'

Example response

{
  "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
  "name": "Harbourside Dental",
  "email": "office@example.co.uk",
  "phone": "0117 496 0123",
  "website": "https://example.co.uk",
  "address": "1 Harbour Road, Bristol",
  "notes": "Side gate code is on the key safe.",
  "logoUrl": "https://example.co.uk",
  "status": "live",
  "isInternal": false,
  "customFields": {
    "contract-number": "CN-1042"
  },
  "tags": [
    "prospect"
  ],
  "createdAt": "2026-11-06T09:30:00.000Z"
}

Whether a client can be archived yet, and what is in the way (upcoming bookings, running repeat bookings)

GET/v1/clients/{id}/archive-check

Permission
client.manage
Answers
200

Parameters

NameInKind
idpathuuidrequired

Response object

  • canArchivebooleanrequired
  • reasonsarray of stringrequired
  • bookingCountintegerrequired

    -9007199254740991 to 9007199254740991

  • jobCountintegerrequired

    -9007199254740991 to 9007199254740991

  • bookingsarray of objectrequired
    • iduuidrequired
    • namestringrequired
    • datestringrequired
    • statusenumrequired

      One of "draft", "open", "active", "complete", "signed_off", "failed"

  • jobsarray of objectrequired
    • iduuidrequired
    • namestringrequired
    • startDatestringrequired
curl "https://app.workscope.co.uk/v1/clients/ID/archive-check" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

{
  "canArchive": false,
  "reasons": [
    "text"
  ],
  "bookingCount": 3,
  "jobCount": 3,
  "bookings": [
    {
      "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
      "name": "Harbourside Dental",
      "date": "2026-11-06",
      "status": "draft"
    }
  ],
  "jobs": [
    {
      "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
      "name": "Harbourside Dental",
      "startDate": "2026-11-06"
    }
  ]
}

A client's contacts

GET/v1/clients/{id}/contacts

Permission
client.view
Answers
200

Parameters

NameInKind
idpathuuidrequired

Response array of object

  • iduuidrequired
  • clientIduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • jobTitlestringrequiredcan be null
  • notesstringrequiredcan be null
  • hasLoginbooleanrequired
  • accessobjectrequired
    • stateenumrequired

      One of "login", "invited", "none"

    • lastSeenAtstringrequiredcan be null
    • invitationIduuidrequiredcan be null
    • invitedAtstringrequiredcan be null
  • emailBlockobjectoptionalcan be null
    • reasonenumrequired

      One of "bounce", "complaint"

    • atstringrequired
    • canUnblockbooleanrequired
curl "https://app.workscope.co.uk/v1/clients/ID/contacts" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

[
  {
    "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
    "clientId": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "name": "Harbourside Dental",
    "email": "office@example.co.uk",
    "phone": "0117 496 0123",
    "jobTitle": "text",
    "notes": "Side gate code is on the key safe.",
    "hasLogin": false,
    "access": {
      "state": "login",
      "lastSeenAt": "2026-11-06T09:30:00.000Z",
      "invitationId": "b7e6d5c4-3b2a-4190-8f7e-6d5c4b3a2918",
      "invitedAt": "2026-11-06T09:30:00.000Z"
    },
    "emailBlock": {
      "reason": "bounce",
      "at": "2026-11-06T09:30:00.000Z",
      "canUnblock": false
    }
  }
]

Add a contact

POST/v1/clients/{id}/contacts

Permission
client.manage
Answers
201

Parameters

NameInKind
idpathuuidrequired

Request body JSON

  • namestringrequired

    1–200 characters

  • emailconstant or stringoptionalcan be null
  • phonestringoptionalcan be null

    Up to 50 characters

  • jobTitlestringoptionalcan be null

    Up to 200 characters

  • notesstringoptionalcan be null

    Up to 5000 characters

Response object

  • iduuidrequired
  • clientIduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • jobTitlestringrequiredcan be null
  • notesstringrequiredcan be null
  • hasLoginbooleanrequired
  • accessobjectrequired
    • stateenumrequired

      One of "login", "invited", "none"

    • lastSeenAtstringrequiredcan be null
    • invitationIduuidrequiredcan be null
    • invitedAtstringrequiredcan be null
  • emailBlockobjectoptionalcan be null
    • reasonenumrequired

      One of "bounce", "complaint"

    • atstringrequired
    • canUnblockbooleanrequired
curl -X POST "https://app.workscope.co.uk/v1/clients/ID/contacts" \
  -H "Authorization: Bearer wsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Harbourside Dental",
    "email": "",
    "phone": "0117 496 0123",
    "jobTitle": "text",
    "notes": "Side gate code is on the key safe."
  }'

Example response

{
  "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
  "clientId": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
  "name": "Harbourside Dental",
  "email": "office@example.co.uk",
  "phone": "0117 496 0123",
  "jobTitle": "text",
  "notes": "Side gate code is on the key safe.",
  "hasLogin": false,
  "access": {
    "state": "login",
    "lastSeenAt": "2026-11-06T09:30:00.000Z",
    "invitationId": "b7e6d5c4-3b2a-4190-8f7e-6d5c4b3a2918",
    "invitedAt": "2026-11-06T09:30:00.000Z"
  },
  "emailBlock": {
    "reason": "bounce",
    "at": "2026-11-06T09:30:00.000Z",
    "canUnblock": false
  }
}

Change a contact

PATCH/v1/clients/{id}/contacts/{childId}

Permission
client.manage
Answers
200

Parameters

NameInKind
idpathuuidrequired
childIdpathuuidrequired

Request body JSON

  • namestringoptional

    1–200 characters

  • emailconstant or stringoptionalcan be null
  • phonestringoptionalcan be null

    Up to 50 characters

  • jobTitlestringoptionalcan be null

    Up to 200 characters

  • notesstringoptionalcan be null

    Up to 5000 characters

Response object

  • iduuidrequired
  • clientIduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • jobTitlestringrequiredcan be null
  • notesstringrequiredcan be null
  • hasLoginbooleanrequired
  • accessobjectrequired
    • stateenumrequired

      One of "login", "invited", "none"

    • lastSeenAtstringrequiredcan be null
    • invitationIduuidrequiredcan be null
    • invitedAtstringrequiredcan be null
  • emailBlockobjectoptionalcan be null
    • reasonenumrequired

      One of "bounce", "complaint"

    • atstringrequired
    • canUnblockbooleanrequired
curl -X PATCH "https://app.workscope.co.uk/v1/clients/ID/contacts/ID" \
  -H "Authorization: Bearer wsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Harbourside Dental",
    "email": "",
    "phone": "0117 496 0123",
    "jobTitle": "text",
    "notes": "Side gate code is on the key safe."
  }'

Example response

{
  "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
  "clientId": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
  "name": "Harbourside Dental",
  "email": "office@example.co.uk",
  "phone": "0117 496 0123",
  "jobTitle": "text",
  "notes": "Side gate code is on the key safe.",
  "hasLogin": false,
  "access": {
    "state": "login",
    "lastSeenAt": "2026-11-06T09:30:00.000Z",
    "invitationId": "b7e6d5c4-3b2a-4190-8f7e-6d5c4b3a2918",
    "invitedAt": "2026-11-06T09:30:00.000Z"
  },
  "emailBlock": {
    "reason": "bounce",
    "at": "2026-11-06T09:30:00.000Z",
    "canUnblock": false
  }
}

Remove a contact

DELETE/v1/clients/{id}/contacts/{childId}

Permission
client.manage
Answers
200

Parameters

NameInKind
idpathuuidrequired
childIdpathuuidrequired

Response object

  • okconstantrequired

    Always true

curl -X DELETE "https://app.workscope.co.uk/v1/clients/ID/contacts/ID" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

{
  "ok": true
}

Email this contact again after one of this company's emails bounced or was marked as spam

POST/v1/clients/{id}/contacts/{childId}/unblock-email

Permission
client.manage
Answers
200

Parameters

NameInKind
idpathuuidrequired
childIdpathuuidrequired

Response object

  • iduuidrequired
  • clientIduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • jobTitlestringrequiredcan be null
  • notesstringrequiredcan be null
  • hasLoginbooleanrequired
  • accessobjectrequired
    • stateenumrequired

      One of "login", "invited", "none"

    • lastSeenAtstringrequiredcan be null
    • invitationIduuidrequiredcan be null
    • invitedAtstringrequiredcan be null
  • emailBlockobjectoptionalcan be null
    • reasonenumrequired

      One of "bounce", "complaint"

    • atstringrequired
    • canUnblockbooleanrequired
curl -X POST "https://app.workscope.co.uk/v1/clients/ID/contacts/ID/unblock-email" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

{
  "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
  "clientId": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
  "name": "Harbourside Dental",
  "email": "office@example.co.uk",
  "phone": "0117 496 0123",
  "jobTitle": "text",
  "notes": "Side gate code is on the key safe.",
  "hasLogin": false,
  "access": {
    "state": "login",
    "lastSeenAt": "2026-11-06T09:30:00.000Z",
    "invitationId": "b7e6d5c4-3b2a-4190-8f7e-6d5c4b3a2918",
    "invitedAt": "2026-11-06T09:30:00.000Z"
  },
  "emailBlock": {
    "reason": "bounce",
    "at": "2026-11-06T09:30:00.000Z",
    "canUnblock": false
  }
}

Import clients (and a main contact each) from spreadsheet rows, already matched to fields; dryRun says what would happen

POST/v1/clients/import

Permission
client.manage
Answers
200

Request body JSON

  • rowsarray of objectrequired

    1–2000 items

    • rowNumberintegerrequired

      1 to 9007199254740991

    • valuesobjectrequired
  • onDuplicateenumoptional

    One of "skip", "update" · Default "skip"

  • dryRunbooleanoptional

    Default false

Response object

  • dryRunbooleanrequired
  • createdintegerrequired

    -9007199254740991 to 9007199254740991

  • updatedintegerrequired

    -9007199254740991 to 9007199254740991

  • skippedintegerrequired

    -9007199254740991 to 9007199254740991

  • failedintegerrequired

    -9007199254740991 to 9007199254740991

  • rowsarray of objectrequired
    • rowNumberintegerrequired

      -9007199254740991 to 9007199254740991

    • namestringrequired
    • outcomeenumrequired

      One of "created", "updated", "skipped", "failed"

    • messagestringrequiredcan be null
curl -X POST "https://app.workscope.co.uk/v1/clients/import" \
  -H "Authorization: Bearer wsk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "rows": [
      {
        "rowNumber": 1,
        "values": {}
      }
    ],
    "onDuplicate": "skip",
    "dryRun": false
  }'

Example response

{
  "dryRun": false,
  "created": -9007199254740991,
  "updated": -9007199254740991,
  "skipped": -9007199254740991,
  "failed": -9007199254740991,
  "rows": [
    {
      "rowNumber": -9007199254740991,
      "name": "Harbourside Dental",
      "outcome": "created",
      "message": "text"
    }
  ]
}

Contacts across all clients

GET/v1/contacts

Permission
client.view
Answers
200

Parameters

NameInKind
clientIdqueryuuid
qquerystring

Response array of object

  • iduuidrequired
  • clientIduuidrequired
  • namestringrequired
  • emailstringrequiredcan be null
  • phonestringrequiredcan be null
  • jobTitlestringrequiredcan be null
  • notesstringrequiredcan be null
  • hasLoginbooleanrequired
  • accessobjectrequired
    • stateenumrequired

      One of "login", "invited", "none"

    • lastSeenAtstringrequiredcan be null
    • invitationIduuidrequiredcan be null
    • invitedAtstringrequiredcan be null
  • emailBlockobjectoptionalcan be null
    • reasonenumrequired

      One of "bounce", "complaint"

    • atstringrequired
    • canUnblockbooleanrequired
  • clientNamestringrequired
curl "https://app.workscope.co.uk/v1/contacts" \
  -H "Authorization: Bearer wsk_your_key_here"

Example response

[
  {
    "id": "3f2a9c1e-6b4d-4e8a-9f1c-2d7b5a0e8c41",
    "clientId": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "name": "Harbourside Dental",
    "email": "office@example.co.uk",
    "phone": "0117 496 0123",
    "jobTitle": "text",
    "notes": "Side gate code is on the key safe.",
    "hasLogin": false,
    "access": {
      "state": "login",
      "lastSeenAt": "2026-11-06T09:30:00.000Z",
      "invitationId": "b7e6d5c4-3b2a-4190-8f7e-6d5c4b3a2918",
      "invitedAt": "2026-11-06T09:30:00.000Z"
    },
    "emailBlock": {
      "reason": "bounce",
      "at": "2026-11-06T09:30:00.000Z",
      "canUnblock": false
    },
    "clientName": "Harbourside Dental"
  }
]