Products

Base URL: https://api.cornerspot.net

Authentication: requests use a bearer token, for example Authorization: Bearer YOUR_API_KEY.

List products

GET /c/api/v1/products

Returns a paginated, filterable page of the team's catalog products. Active products are returned by default; pass filter[include_inactive]=true to include inactive ones. Requires the products_read scope and the CRM module.

Query parameters

FIELDTYPEDESCRIPTION
querystringFull-text search over name, code, description, category.
filter[include_inactive]stringSet to true to include inactive products. Default: only active products are returned.
filter[category]stringComma-separated category values; returns products in any of them.
filter[pricing_model]stringComma-separated pricing models: one_time, recurring.
filter[product_category_ids]stringComma-separated ProductCategory ids; returns products belonging to any of them.
filter[tags]stringComma-separated tag ids; returns products carrying any of them.
sortstringSort column, - prefix for descending. One of name,code,category,default_price,active,pricing_model,billing_frequency,default_billing_term_months,created_at,updated_at. Default -updated_at.
pageinteger1-based page number.
per_pageintegerPage size (1–100, default 25).

Code samples

curl --request GET \
  --url 'https://api.cornerspot.net/c/api/v1/products' \
  --header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/products', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const data = await response.json();
console.log(data);
// Node.js 18+ (native fetch)
const response = await fetch('https://api.cornerspot.net/c/api/v1/products', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const data = await response.json();
console.log(data);
import json
import urllib.request

url = "https://api.cornerspot.net/c/api/v1/products"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
}

request = urllib.request.Request(url, headers=headers, method="GET")

with urllib.request.urlopen(request) as response:
    data = json.loads(response.read().decode("utf-8"))
    print(data)
require "json"
require "net/http"

uri = URI("https://api.cornerspot.net/c/api/v1/products")

request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts JSON.parse(response.body)
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.cornerspot.net/c/api/v1/products',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = curl_exec($curl);
curl_close($curl);

$data = json_decode($response, true);
print_r($data);

Responses

STATUSDESCRIPTION
200 OKa page of products
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the CRM module
403 Forbiddenthe key lacks the products_read scope

Create a product

POST /c/api/v1/products

Creates a catalog product. name and pricing_model are required. Requires products_write.

Request body

FIELDTYPEDESCRIPTION
productobject
product.namestring · requiredRequired — product name.
product.codestring
product.descriptionstring
product.default_pricestringDecimal string (e.g. "99.00").
product.currency_idstring
product.activeboolean
product.categorystring
product.unitstring
product.pricing_modelstring · required
one of one_time, recurring
Required.
product.billing_frequencystring
one of monthly, quarterly, semi_annual, annual
Required when pricing_model is recurring.
product.default_billing_term_monthsintegerRequired when pricing_model is recurring.
product.custom_fieldsobject
product.tag_ids[]array of string
product.product_category_ids[]array of string
product.tax_rate_ids[]array of string
product.discount_definition_ids[]array of string

Code samples

curl --request POST \
  --url 'https://api.cornerspot.net/c/api/v1/products' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "product": {
    "name": "string",
    "code": "string",
    "description": "string",
    "default_price": "string",
    "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
    "active": true,
    "category": "string",
    "unit": "string",
    "pricing_model": "one_time",
    "billing_frequency": "monthly",
    "default_billing_term_months": 1,
    "custom_fields": {},
    "tag_ids": [
      "abc123"
    ],
    "product_category_ids": [
      "abc123"
    ],
    "tax_rate_ids": [
      "abc123"
    ],
    "discount_definition_ids": [
      "abc123"
    ]
  }
}'
const response = await fetch('https://api.cornerspot.net/c/api/v1/products', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'
  },
  body: JSON.stringify({
    "product": {
      "name": "string",
      "code": "string",
      "description": "string",
      "default_price": "string",
      "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
      "active": true,
      "category": "string",
      "unit": "string",
      "pricing_model": "one_time",
      "billing_frequency": "monthly",
      "default_billing_term_months": 1,
      "custom_fields": {},
      "tag_ids": [
        "abc123"
      ],
      "product_category_ids": [
        "abc123"
      ],
      "tax_rate_ids": [
        "abc123"
      ],
      "discount_definition_ids": [
        "abc123"
      ]
    }
  })
});

const data = await response.json();
console.log(data);
// Node.js 18+ (native fetch)
const response = await fetch('https://api.cornerspot.net/c/api/v1/products', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'
  },
  body: JSON.stringify({
    "product": {
      "name": "string",
      "code": "string",
      "description": "string",
      "default_price": "string",
      "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
      "active": true,
      "category": "string",
      "unit": "string",
      "pricing_model": "one_time",
      "billing_frequency": "monthly",
      "default_billing_term_months": 1,
      "custom_fields": {},
      "tag_ids": [
        "abc123"
      ],
      "product_category_ids": [
        "abc123"
      ],
      "tax_rate_ids": [
        "abc123"
      ],
      "discount_definition_ids": [
        "abc123"
      ]
    }
  })
});

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const data = await response.json();
console.log(data);
import json
import urllib.request

url = "https://api.cornerspot.net/c/api/v1/products"
payload = json.dumps({
  "product": {
    "name": "string",
    "code": "string",
    "description": "string",
    "default_price": "string",
    "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
    "active": true,
    "category": "string",
    "unit": "string",
    "pricing_model": "one_time",
    "billing_frequency": "monthly",
    "default_billing_term_months": 1,
    "custom_fields": {},
    "tag_ids": [
      "abc123"
    ],
    "product_category_ids": [
      "abc123"
    ],
    "tax_rate_ids": [
      "abc123"
    ],
    "discount_definition_ids": [
      "abc123"
    ]
  }
}).encode("utf-8")
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_API_KEY",
}

request = urllib.request.Request(url, data=payload, headers=headers, method="POST")

with urllib.request.urlopen(request) as response:
    data = json.loads(response.read().decode("utf-8"))
    print(data)
require "json"
require "net/http"

uri = URI("https://api.cornerspot.net/c/api/v1/products")

request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer YOUR_API_KEY"
request.body = JSON.generate({
  "product": {
    "name": "string",
    "code": "string",
    "description": "string",
    "default_price": "string",
    "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
    "active": true,
    "category": "string",
    "unit": "string",
    "pricing_model": "one_time",
    "billing_frequency": "monthly",
    "default_billing_term_months": 1,
    "custom_fields": {},
    "tag_ids": [
      "abc123"
    ],
    "product_category_ids": [
      "abc123"
    ],
    "tax_rate_ids": [
      "abc123"
    ],
    "discount_definition_ids": [
      "abc123"
    ]
  }
})

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts JSON.parse(response.body)
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.cornerspot.net/c/api/v1/products',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_API_KEY',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'product' => [
        'name' => 'string',
        'code' => 'string',
        'description' => 'string',
        'default_price' => 'string',
        'currency_id' => '1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d',
        'active' => true,
        'category' => 'string',
        'unit' => 'string',
        'pricing_model' => 'one_time',
        'billing_frequency' => 'monthly',
        'default_billing_term_months' => 1,
        'custom_fields' => [],
        'tag_ids' => [
            'abc123',
        ],
        'product_category_ids' => [
            'abc123',
        ],
        'tax_rate_ids' => [
            'abc123',
        ],
        'discount_definition_ids' => [
            'abc123',
        ],
    ],
]),
]);

$response = curl_exec($curl);
curl_close($curl);

$data = json_decode($response, true);
print_r($data);

Responses

STATUSDESCRIPTION
201 Createdcreated
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the CRM module
403 Forbiddenthe key lacks the products_write scope
422 Unprocessable Contentvalidation errors (e.g. missing name)

Get a product

GET /c/api/v1/products/{id}

Path parameters

FIELDTYPEDESCRIPTION
idstring · requiredProduct id.

Code samples

curl --request GET \
  --url 'https://api.cornerspot.net/c/api/v1/products/abc123' \
  --header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/products/abc123', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const data = await response.json();
console.log(data);
// Node.js 18+ (native fetch)
const response = await fetch('https://api.cornerspot.net/c/api/v1/products/abc123', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const data = await response.json();
console.log(data);
import json
import urllib.request

url = "https://api.cornerspot.net/c/api/v1/products/abc123"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
}

request = urllib.request.Request(url, headers=headers, method="GET")

with urllib.request.urlopen(request) as response:
    data = json.loads(response.read().decode("utf-8"))
    print(data)
require "json"
require "net/http"

uri = URI("https://api.cornerspot.net/c/api/v1/products/abc123")

request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts JSON.parse(response.body)
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.cornerspot.net/c/api/v1/products/abc123',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = curl_exec($curl);
curl_close($curl);

$data = json_decode($response, true);
print_r($data);

Responses

STATUSDESCRIPTION
200 OKthe product
401 Unauthorizedmissing or invalid API key
404 Not Foundno such product in this team

Update a product

PATCH /c/api/v1/products/{id}

Updates any field(s) on the product. Requires products_write.

Path parameters

FIELDTYPEDESCRIPTION
idstring · requiredProduct id.

Request body

FIELDTYPEDESCRIPTION
productobject
product.namestring
product.codestring
product.descriptionstring
product.default_pricestring
product.currency_idstring
product.activeboolean
product.categorystring
product.unitstring
product.pricing_modelstring
one of one_time, recurring
product.billing_frequencystring
one of monthly, quarterly, semi_annual, annual
product.default_billing_term_monthsinteger
product.custom_fieldsobject
product.tag_ids[]array of string
product.product_category_ids[]array of string
product.tax_rate_ids[]array of string
product.discount_definition_ids[]array of string

Code samples

curl --request PATCH \
  --url 'https://api.cornerspot.net/c/api/v1/products/abc123' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "product": {
    "name": "string",
    "code": "string",
    "description": "string",
    "default_price": "string",
    "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
    "active": true,
    "category": "string",
    "unit": "string",
    "pricing_model": "one_time",
    "billing_frequency": "monthly",
    "default_billing_term_months": 1,
    "custom_fields": {},
    "tag_ids": [
      "abc123"
    ],
    "product_category_ids": [
      "abc123"
    ],
    "tax_rate_ids": [
      "abc123"
    ],
    "discount_definition_ids": [
      "abc123"
    ]
  }
}'
const response = await fetch('https://api.cornerspot.net/c/api/v1/products/abc123', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'
  },
  body: JSON.stringify({
    "product": {
      "name": "string",
      "code": "string",
      "description": "string",
      "default_price": "string",
      "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
      "active": true,
      "category": "string",
      "unit": "string",
      "pricing_model": "one_time",
      "billing_frequency": "monthly",
      "default_billing_term_months": 1,
      "custom_fields": {},
      "tag_ids": [
        "abc123"
      ],
      "product_category_ids": [
        "abc123"
      ],
      "tax_rate_ids": [
        "abc123"
      ],
      "discount_definition_ids": [
        "abc123"
      ]
    }
  })
});

const data = await response.json();
console.log(data);
// Node.js 18+ (native fetch)
const response = await fetch('https://api.cornerspot.net/c/api/v1/products/abc123', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'
  },
  body: JSON.stringify({
    "product": {
      "name": "string",
      "code": "string",
      "description": "string",
      "default_price": "string",
      "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
      "active": true,
      "category": "string",
      "unit": "string",
      "pricing_model": "one_time",
      "billing_frequency": "monthly",
      "default_billing_term_months": 1,
      "custom_fields": {},
      "tag_ids": [
        "abc123"
      ],
      "product_category_ids": [
        "abc123"
      ],
      "tax_rate_ids": [
        "abc123"
      ],
      "discount_definition_ids": [
        "abc123"
      ]
    }
  })
});

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const data = await response.json();
console.log(data);
import json
import urllib.request

url = "https://api.cornerspot.net/c/api/v1/products/abc123"
payload = json.dumps({
  "product": {
    "name": "string",
    "code": "string",
    "description": "string",
    "default_price": "string",
    "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
    "active": true,
    "category": "string",
    "unit": "string",
    "pricing_model": "one_time",
    "billing_frequency": "monthly",
    "default_billing_term_months": 1,
    "custom_fields": {},
    "tag_ids": [
      "abc123"
    ],
    "product_category_ids": [
      "abc123"
    ],
    "tax_rate_ids": [
      "abc123"
    ],
    "discount_definition_ids": [
      "abc123"
    ]
  }
}).encode("utf-8")
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_API_KEY",
}

request = urllib.request.Request(url, data=payload, headers=headers, method="PATCH")

with urllib.request.urlopen(request) as response:
    data = json.loads(response.read().decode("utf-8"))
    print(data)
require "json"
require "net/http"

uri = URI("https://api.cornerspot.net/c/api/v1/products/abc123")

request = Net::HTTP::Patch.new(uri)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer YOUR_API_KEY"
request.body = JSON.generate({
  "product": {
    "name": "string",
    "code": "string",
    "description": "string",
    "default_price": "string",
    "currency_id": "1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d",
    "active": true,
    "category": "string",
    "unit": "string",
    "pricing_model": "one_time",
    "billing_frequency": "monthly",
    "default_billing_term_months": 1,
    "custom_fields": {},
    "tag_ids": [
      "abc123"
    ],
    "product_category_ids": [
      "abc123"
    ],
    "tax_rate_ids": [
      "abc123"
    ],
    "discount_definition_ids": [
      "abc123"
    ]
  }
})

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts JSON.parse(response.body)
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.cornerspot.net/c/api/v1/products/abc123',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Authorization: Bearer YOUR_API_KEY',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'product' => [
        'name' => 'string',
        'code' => 'string',
        'description' => 'string',
        'default_price' => 'string',
        'currency_id' => '1f2e3d4c-5b6a-4789-9c0d-1e2f3a4b5c6d',
        'active' => true,
        'category' => 'string',
        'unit' => 'string',
        'pricing_model' => 'one_time',
        'billing_frequency' => 'monthly',
        'default_billing_term_months' => 1,
        'custom_fields' => [],
        'tag_ids' => [
            'abc123',
        ],
        'product_category_ids' => [
            'abc123',
        ],
        'tax_rate_ids' => [
            'abc123',
        ],
        'discount_definition_ids' => [
            'abc123',
        ],
    ],
]),
]);

$response = curl_exec($curl);
curl_close($curl);

$data = json_decode($response, true);
print_r($data);

Responses

STATUSDESCRIPTION
200 OKupdated
401 Unauthorizedmissing or invalid API key
403 Forbiddenthe key lacks the products_write scope
404 Not Foundno such product in this team
422 Unprocessable Contentvalidation errors (e.g. blank name)

Delete (soft) a product

DELETE /c/api/v1/products/{id}

Soft-deletes the product. Line items that reference it have their product_id nulled. Requires products_write.

Path parameters

FIELDTYPEDESCRIPTION
idstring · requiredProduct id.

Code samples

curl --request DELETE \
  --url 'https://api.cornerspot.net/c/api/v1/products/abc123' \
  --header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/products/abc123', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const data = await response.json();
console.log(data);
// Node.js 18+ (native fetch)
const response = await fetch('https://api.cornerspot.net/c/api/v1/products/abc123', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

if (!response.ok) {
  throw new Error(`Request failed: ${response.status}`);
}

const data = await response.json();
console.log(data);
import json
import urllib.request

url = "https://api.cornerspot.net/c/api/v1/products/abc123"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
}

request = urllib.request.Request(url, headers=headers, method="DELETE")

with urllib.request.urlopen(request) as response:
    data = json.loads(response.read().decode("utf-8"))
    print(data)
require "json"
require "net/http"

uri = URI("https://api.cornerspot.net/c/api/v1/products/abc123")

request = Net::HTTP::Delete.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts JSON.parse(response.body)
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://api.cornerspot.net/c/api/v1/products/abc123',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = curl_exec($curl);
curl_close($curl);

$data = json_decode($response, true);
print_r($data);

Responses

STATUSDESCRIPTION
204 No Contentdeleted
401 Unauthorizedmissing or invalid API key
403 Forbiddenthe key lacks the products_write scope
404 Not Foundno such product in this team

Was this article helpful?