Portal Documents

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

FIELDTYPEDESCRIPTION
portal_user_idstringFilter to documents belonging to this portal user. Requires portal_users_read.
account_idstringFilter to documents belonging to this account. Requires portal_branding_read.
pageinteger1-based page number.
per_pageintegerPage 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

STATUSDESCRIPTION
200 OKa page of portal documents
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the Member Portal module
403 Forbiddenthe 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

STATUSDESCRIPTION
201 Createdcreated
400 Bad Requestno file or signed_id was provided
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the Member Portal module
403 Forbiddenthe key lacks the portal_branding_write scope
422 Unprocessable Contentportal_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

FIELDTYPEDESCRIPTION
idstring · requiredPortal 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

STATUSDESCRIPTION
200 OKthe portal document
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the Member Portal module
403 Forbiddenthe key lacks the portal_branding_read scope
404 Not Foundno 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

FIELDTYPEDESCRIPTION
idstring · requiredPortal 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

STATUSDESCRIPTION
200 OKupdated
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the Member Portal module
403 Forbiddenthe key lacks the portal_branding_write scope
404 Not Foundno such document in this team
422 Unprocessable Contentinvalid 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

FIELDTYPEDESCRIPTION
idstring · requiredPortal 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

STATUSDESCRIPTION
204 No Contentdeleted
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the Member Portal module
403 Forbiddenthe key lacks the portal_branding_write scope
404 Not Foundno 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

FIELDTYPEDESCRIPTION
idstring · requiredPortal 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

STATUSDESCRIPTION
200 OKfile stream
401 Unauthorizedmissing or invalid API key
402 Payment Requiredthe team's plan doesn't include the Member Portal module
403 Forbiddenthe key lacks the portal_branding_read scope
404 Not Foundno such document in this team

Was this article helpful?