Base URL: https://api.cornerspot.net
Authentication: requests use a bearer token, for example Authorization: Bearer YOUR_API_KEY.
List portal documents
GET /c/api/v1/portal/documents
Returns a paginated list of portal documents for the team.
The result set depends on the query parameters: No filter → team-shared documents (requires portal_branding_read). account_id → documents scoped to that account (requires portal_branding_read). portal_user_id → documents scoped to that portal user (requires portal_users_read).
Requires the Member Portal module.
Query parameters
| FIELD | TYPE | DESCRIPTION |
|---|---|---|
portal_user_id | string | Filter to documents belonging to this portal user. Requires portal_users_read. |
account_id | string | Filter to documents belonging to this account. Requires portal_branding_read. |
page | integer | 1-based page number. |
per_page | integer | Page size (1–100, default 25). |
Code samples
curl --request GET \
--url 'https://api.cornerspot.net/c/api/v1/portal/documents' \
--header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/portal/documents', {
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/portal/documents', {
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/portal/documents"
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/portal/documents")
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/portal/documents',
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
| STATUS | DESCRIPTION |
|---|---|
200 OK | a page of portal documents |
401 Unauthorized | missing or invalid API key |
402 Payment Required | the team's plan doesn't include the Member Portal module |
403 Forbidden | the key lacks the portal_branding_read scope |
Upload a portal document
POST /c/api/v1/portal/documents
Creates a new portal document by uploading a file via multipart/form-data.
The document is scoped as follows: Neither portal_user_id nor account_id → team-shared document (requires portal_branding_write). account_id present → account-scoped document (requires portal_branding_write). portal_user_id present → user-scoped document (requires portal_users_write). Supplying both portal_user_id and account_id returns 422 scope_conflict.
Alternatively, pass a pre-created Active Storage signed_id (direct upload) instead of a file part. Omitting both returns 400 file_required.
Allowed file types: PDF, images (PNG/JPEG/GIF/WebP/HEIC), Office documents, plain text, CSV, Markdown. Maximum file size: 10 MB. Returns 415 for unsupported types and 413 for oversized files.
Requires the Member Portal module.
Request body
This endpoint accepts a multipart/form-data request body.
Code samples
curl --request POST \
--url 'https://api.cornerspot.net/c/api/v1/portal/documents' \
--header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/portal/documents', {
method: 'POST',
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/portal/documents', {
method: 'POST',
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/portal/documents"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
}
request = urllib.request.Request(url, 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/portal/documents")
request = Net::HTTP::Post.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/portal/documents',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
],
]);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response, true);
print_r($data);
Responses
| STATUS | DESCRIPTION |
|---|---|
201 Created | created |
400 Bad Request | no file or signed_id was provided |
401 Unauthorized | missing or invalid API key |
402 Payment Required | the team's plan doesn't include the Member Portal module |
403 Forbidden | the key lacks the portal_branding_write scope |
422 Unprocessable Content | portal_user_id and account_id are mutually exclusive |
Get a portal document
GET /c/api/v1/portal/documents/{id}
Returns a single portal document by id. Requires portal_branding_read (shared/account docs) or portal_users_read (user-scoped docs). Requires the Member Portal module.
Path parameters
| FIELD | TYPE | DESCRIPTION |
|---|---|---|
id | string · required | Portal document id. |
Code samples
curl --request GET \
--url 'https://api.cornerspot.net/c/api/v1/portal/documents/abc123' \
--header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/portal/documents/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/portal/documents/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/portal/documents/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/portal/documents/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/portal/documents/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
| STATUS | DESCRIPTION |
|---|---|
200 OK | the portal document |
401 Unauthorized | missing or invalid API key |
402 Payment Required | the team's plan doesn't include the Member Portal module |
403 Forbidden | the key lacks the portal_branding_read scope |
404 Not Found | no such document in this team |
Update a portal document
PATCH /c/api/v1/portal/documents/{id}
Updates the metadata and/or replaces the attached file for a portal document.
To replace the file, include a file form-data part or a new signed_id. Scope (portal_user_id / account_id) cannot be changed after creation.
Requires portal_branding_write (shared/account docs) or portal_users_write (user-scoped docs). Requires the Member Portal module.
Path parameters
| FIELD | TYPE | DESCRIPTION |
|---|---|---|
id | string · required | Portal document id. |
Request body
This endpoint accepts a multipart/form-data request body.
Code samples
curl --request PATCH \
--url 'https://api.cornerspot.net/c/api/v1/portal/documents/abc123' \
--header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/portal/documents/abc123', {
method: 'PATCH',
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/portal/documents/abc123', {
method: 'PATCH',
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/portal/documents/abc123"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
}
request = urllib.request.Request(url, 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/portal/documents/abc123")
request = Net::HTTP::Patch.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/portal/documents/abc123',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
],
]);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response, true);
print_r($data);
Responses
| STATUS | DESCRIPTION |
|---|---|
200 OK | updated |
401 Unauthorized | missing or invalid API key |
402 Payment Required | the team's plan doesn't include the Member Portal module |
403 Forbidden | the key lacks the portal_branding_write scope |
404 Not Found | no such document in this team |
422 Unprocessable Content | invalid signed_id |
Delete a portal document
DELETE /c/api/v1/portal/documents/{id}
Permanently deletes a portal document and its attached file. Requires portal_branding_write (shared/account docs) or portal_users_write (user-scoped docs). Requires the Member Portal module.
Path parameters
| FIELD | TYPE | DESCRIPTION |
|---|---|---|
id | string · required | Portal document id. |
Code samples
curl --request DELETE \
--url 'https://api.cornerspot.net/c/api/v1/portal/documents/abc123' \
--header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/portal/documents/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/portal/documents/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/portal/documents/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/portal/documents/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/portal/documents/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
| STATUS | DESCRIPTION |
|---|---|
204 No Content | deleted |
401 Unauthorized | missing or invalid API key |
402 Payment Required | the team's plan doesn't include the Member Portal module |
403 Forbidden | the key lacks the portal_branding_write scope |
404 Not Found | no such document in this team |
Download a portal document's file
GET /c/api/v1/portal/documents/{id}/download
Streams the raw file as an attachment (Content-Disposition: attachment). The response Content-Type and filename mirror the stored Active Storage blob.
Requires portal_branding_read (shared/account docs) or portal_users_read (user-scoped docs). Requires the Member Portal module.
Path parameters
| FIELD | TYPE | DESCRIPTION |
|---|---|---|
id | string · required | Portal document id. |
Code samples
curl --request GET \
--url 'https://api.cornerspot.net/c/api/v1/portal/documents/abc123/download' \
--header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.cornerspot.net/c/api/v1/portal/documents/abc123/download', {
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/portal/documents/abc123/download', {
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/portal/documents/abc123/download"
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/portal/documents/abc123/download")
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/portal/documents/abc123/download',
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
| STATUS | DESCRIPTION |
|---|---|
200 OK | file stream |
401 Unauthorized | missing or invalid API key |
402 Payment Required | the team's plan doesn't include the Member Portal module |
403 Forbidden | the key lacks the portal_branding_read scope |
404 Not Found | no such document in this team |
