Klantly Developers

API reference

Deals

The cards on your pipeline board: create, update, move to another stage, win, lose and archive.

Endpoints

List deals

GET /api/v1/deals

A list of deals, newest first. Archived deals are left out by default; use filter[archived] to include them. Filter by status, stage, customer, owner or modification date.

Scope
deals.read — Read deals and pipeline stages
Required feature
pipeline

Query parameters

NameTypeDescription
limit integer Number of results per page. from 1 to 100 · default: 50
cursor string The next_cursor or prev_cursor from meta of the previous response.
sort string Sort by created_at, updated_at or stage_changed_at; a minus sign in front means descending. one of: -created_at, created_at, -updated_at, updated_at, -stage_changed_at, stage_changed_at · default: -created_at
filter[status] string Only open, won or lost deals. one of: open, won, lost
filter[stage_id] integer Only deals in this stage (the id from List pipeline stages).
filter[customer_id] string (uuid) Only deals of this customer.
filter[assigned_user_id] integer Only deals assigned to this user.
filter[archived] string false (default) shows only deals on the board, true only archived ones, all both. one of: false, true, all · default: false
filter[updated_since] string (date-time) Only what changed since this moment: ISO 8601 with a time zone, for example 2026-09-14T10:15:00Z. Useful for synchronising.

Example request

cURL
curl "https://app.klantly.com/api/v1/deals?filter[status]=open" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('GET', 'deals', [
    'query' => [
        'filter[status]' => 'open',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals?filter[status]=open', {
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.get(
    "https://app.klantly.com/api/v1/deals",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    params={
        "filter[status]": "open"
    },
)
data = response.json()["data"]

Response 200

The response is a list with cursor pagination: data contains the objects, meta the pagination.

Example response
{
  "data": [
    {
      "object": "deal",
      "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
      "title": "Veranda 5x3 m",
      "description": null,
      "status": "open",
      "value": "8450.00",
      "currency": "EUR",
      "value_source": "manual",
      "stage": {
        "object": "pipeline_stage",
        "id": "3"
      },
      "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
      "assigned_user_id": "7",
      "source": "api",
      "lost_reason": null,
      "is_archived": false,
      "stage_changed_at": "2026-09-14T10:15:00Z",
      "won_at": null,
      "lost_at": null,
      "archived_at": null,
      "created_at": "2026-09-14T10:15:00Z",
      "updated_at": "2026-09-14T10:15:00Z"
    }
  ],
  "meta": {
    "limit": 50,
    "next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
    "prev_cursor": null
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Retrieve a deal

GET /api/v1/deals/{deal}

One deal by id. The response includes an ETag you can send in If-Match when updating.

Scope
deals.read — Read deals and pipeline stages
Required feature
pipeline

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Example request

cURL
curl "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('GET', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.get(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Create a deal

POST /api/v1/deals

Puts a customer on the pipeline board. A customer can have only one open deal at a time: if there already is one, you get 409 with its id in deal_id. Without stage_id the deal lands in the default stage. If you send value, Klantly keeps that amount instead of calculating it from the quotes.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Body (JSON)

FieldTypeDescription
customer_id required string (uuid) The customer of the deal.
title optional string Title of the deal. can be empty (null) · at most 255 characters
description optional string Description. can be empty (null) · at most 10000 characters
value optional number Value as a string with two decimals, for example "8450.00". When creating or updating you may also send a number. can be empty (null) · from 0 to 99999999
stage_id optional integer The stage the deal goes into. Without stage_id: the default stage. can be empty (null)
assigned_user_id optional integer The user handling the deal, or null. can be empty (null)

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/deals" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
  -d '{
  "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
  "title": "Veranda 5x3 m",
  "value": "8450.00"
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'deals', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
        'title' => 'Veranda 5x3 m',
        'value' => '8450.00',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
  body: JSON.stringify({
  "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
  "title": "Veranda 5x3 m",
  "value": "8450.00"
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/deals",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
    json={
        "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
        "title": "Veranda 5x3 m",
        "value": "8450.00"
    },
)
data = response.json()["data"]

Response 201

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Update a deal

PATCH /api/v1/deals/{deal}

Changes only the fields you send. To change the stage, use move, win or lose. Sending value sets value_source to manual.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send the ETag in If-Match and you will never accidentally overwrite a newer version.

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Body (JSON)

FieldTypeDescription
title optional string Title of the deal. at most 255 characters
description optional string Description. can be empty (null) · at most 10000 characters
value optional number Value as a string with two decimals, for example "8450.00". When creating or updating you may also send a number. from 0 to 99999999
assigned_user_id optional integer The user handling the deal, or null. can be empty (null)

Example request

cURL
curl -X PATCH "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "value": "9100.00",
  "assigned_user_id": 7
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('PATCH', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
    'json' => [
        'value' => '9100.00',
        'assigned_user_id' => 7,
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "value": "9100.00",
  "assigned_user_id": 7
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.patch(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
    },
    json={
        "value": "9100.00",
        "assigned_user_id": 7
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Move a deal

POST /api/v1/deals/{deal}/move

Moves the deal to another stage, exactly like dragging it on the board. If that is a won or lost stage, the deal becomes won or lost too.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Body (JSON)

FieldTypeDescription
stage_id required integer The id of the stage the deal moves to (from List pipeline stages).
notes optional string Optional note; kept in the history of the deal together with the stage change. can be empty (null) · at most 500 characters

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
  -d '{
  "stage_id": 3
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'stage_id' => 3,
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
  body: JSON.stringify({
  "stage_id": 3
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
    json={
        "stage_id": 3
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Win a deal

POST /api/v1/deals/{deal}/win

Moves the deal to the stage your company has set up as won. If it is already won, nothing changes.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Lose a deal

POST /api/v1/deals/{deal}/lose

Moves the deal to the stage your company has set up as lost, optionally with a reason.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Body (JSON)

FieldTypeDescription
lost_reason optional string Why the deal was lost, or null. can be empty (null) · at most 255 characters

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
  -d '{
  "lost_reason": "Te duur"
}'
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
    'json' => [
        'lost_reason' => 'Te duur',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
  body: JSON.stringify({
  "lost_reason": "Te duur"
}),
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
    json={
        "lost_reason": "Te duur"
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Archive a deal

POST /api/v1/deals/{deal}/archive

Takes the deal off the board without deleting it. Deals cannot be deleted through the API.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

Restore a deal

POST /api/v1/deals/{deal}/unarchive

Puts an archived deal back on the board.

Scope
deals.write — Create, update, move and archive deals
Required feature
pipeline

Send an Idempotency-Key and a retry after a timeout will never create a duplicate record.

Path parameters

NameTypeDescription
deal required string (uuid) The id (UUID) of the deal.

Example request

cURL
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive" \
  -H "Authorization: Bearer $KLANTLY_API_KEY" \
  -H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
PHP
$client = new \GuzzleHttp\Client([
    'base_uri' => 'https://app.klantly.com/api/v1/',
    'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);

$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive', [
    'headers' => [
        'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
    ],
]);

$data = json_decode((string) $response->getBody(), true)['data'];
JavaScript
const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
    'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
  },
});

const { data } = await response.json();
Python
import os

import requests

response = requests.post(
    "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive",
    headers={
        "Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
        "Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    },
)
data = response.json()["data"]

Response 200

Example response
{
  "data": {
    "object": "deal",
    "id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
    "title": "Veranda 5x3 m",
    "description": null,
    "status": "open",
    "value": "8450.00",
    "currency": "EUR",
    "value_source": "manual",
    "stage": {
      "object": "pipeline_stage",
      "id": "3"
    },
    "customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
    "assigned_user_id": "7",
    "source": "api",
    "lost_reason": null,
    "is_archived": false,
    "stage_changed_at": "2026-09-14T10:15:00Z",
    "won_at": null,
    "lost_at": null,
    "archived_at": null,
    "created_at": "2026-09-14T10:15:00Z",
    "updated_at": "2026-09-14T10:15:00Z"
  }
}

Possible errors

In addition, every endpoint can return the general errors, such as an invalid key or a reached limit. See all error codes.

The object

All fields are always present; a field without a value is null.

FieldTypeDescription
object string Always "deal".
id string (uuid) Unique id (UUID).
title string Title of the deal.
description string Description. can be empty (null)
status string open, won or lost; follows from the stage. one of: open, won, lost
value string Value as a string with two decimals, for example "8450.00". When creating or updating you may also send a number.
currency string Always "EUR".
value_source string quotes: the value follows from the linked quotes; manual: set by hand. one of: quotes, manual
stage object The stage the deal is in; the names are in List pipeline stages. can be empty (null)
stage.object string Always "pipeline_stage".
stage.id string Id of the stage.
customer_id string (uuid) The customer of the deal. can be empty (null)
assigned_user_id string The user handling the deal, or null. can be empty (null)
source string Where the deal came from; through the API that is api. can be empty (null)
lost_reason string Why the deal was lost, or null. can be empty (null)
is_archived boolean Archived: no longer on the board.
stage_changed_at string (date-time) When the deal last changed stage. can be empty (null)
won_at string (date-time) When the deal was won. can be empty (null)
lost_at string (date-time) When the deal was lost. can be empty (null)
archived_at string (date-time) When the deal was archived. can be empty (null)
created_at string (date-time) Created at (UTC).
updated_at string (date-time) Last updated at (UTC).