Skip to content

Cesivi Server - REST API

HomeDocumentationFeatures → REST API


Overview

The Cesivi Server implements a comprehensive REST API compatible with SharePoint Server Subscription Edition and SharePoint Online. The REST API provides 17+ endpoints with full OData v3 query support for modern web applications.

Status:PRODUCTION READY (98%+ coverage) Base URL: /_api Format: JSON (SharePoint Online compatible) Performance: <5ms average response time


Quick Start

Basic Request

GET /_api/web HTTP/1.1
Host: localhost:5000
Accept: application/json;odata=verbose
Authorization: Basic YWRtaW46cGFzc3dvcmQ=

JavaScript Example

fetch('http://localhost:5000/_api/web/lists', {
  headers: {
    'Accept': 'application/json;odata=verbose',
    'Authorization': 'Basic ' + btoa('admin:password')
  }
})
.then(response => response.json())
.then(data => console.log(data.d.results));

PowerShell Example

$headers = @{
    "Authorization" = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("admin:password"))
    "Accept" = "application/json;odata=verbose"
}

Invoke-RestMethod -Uri "http://localhost:5000/_api/web/lists" -Headers $headers

Available Endpoints

Web & Site Operations

Get Current Web

GET /_api/web

Returns metadata for the current web (site).

Response:

{
  "d": {
    "__metadata": { "type": "SP.Web" },
    "Id": "8ee3228a-72b3-4674-8282-f07e0f4a2db2",
    "Title": "Root Web",
    "Url": "http://localhost:5000",
    "ServerRelativeUrl": "/",
    "Description": "Mock SharePoint Root Web",
    "Created": "2025-01-01T00:00:00Z",
    "LastItemModifiedDate": "2025-11-15T00:00:00Z",
    "Language": 1033,
    "WebTemplate": "STS",
    "Configuration": 0
  }
}

Get Site Collection

GET /_api/site

Returns site collection metadata.

Response:

{
  "d": {
    "__metadata": { "type": "SP.Site" },
    "Id": "12345678-1234-1234-1234-123456789012",
    "Url": "http://localhost:5000",
    "ServerRelativeUrl": "/"
  }
}

Get Subwebs

GET /_api/web/webs

Returns child webs (subsites).

Response:

{
  "d": {
    "results": [
      {
        "__metadata": { "type": "SP.Web" },
        "Id": "abc-123-def-456",
        "Title": "Subsite 1",
        "Url": "http://localhost:5000/subsite1"
      }
    ]
  }
}

Get Current User

GET /_api/web/currentuser

Returns information about the currently authenticated user.

Response:

{
  "d": {
    "__metadata": { "type": "SP.User" },
    "Id": 1,
    "LoginName": "i:0#.w|domain\\admin",
    "Title": "Administrator",
    "Email": "admin@localhost"
  }
}

Get Context Info

POST /_api/contextinfo

Returns form digest and context information.

Response:

{
  "d": {
    "GetContextWebInformation": {
      "FormDigestValue": "0x1234567890ABCDEF...",
      "FormDigestTimeoutSeconds": 1800,
      "WebFullUrl": "http://localhost:5000"
    }
  }
}


List Operations

Get All Lists

GET /_api/web/lists

Returns all lists in the current web.

Response:

{
  "d": {
    "results": [
      {
        "__metadata": { "type": "SP.List" },
        "Id": "abc-123-def-456",
        "Title": "Documents",
        "BaseType": 1,
        "BaseTemplate": 101,
        "Hidden": false,
        "ItemCount": 10,
        "Description": "Shared document library",
        "Created": "2025-01-01T00:00:00Z"
      }
    ]
  }
}

Get List by Title

GET /_api/web/lists/getbytitle('Documents')

Returns a specific list by title.

Response:

{
  "d": {
    "__metadata": { "type": "SP.List" },
    "Id": "abc-123-def-456",
    "Title": "Documents",
    "BaseType": 1,
    "Description": "Shared document library",
    "ItemCount": 10
  }
}

Get List by GUID

GET /_api/web/lists(guid'{list-id}')

Returns a specific list by GUID.

Create List

POST /_api/web/lists

Request Body:

{
  "__metadata": { "type": "SP.List" },
  "Title": "New List",
  "Description": "My new list",
  "BaseTemplate": 100,
  "AllowContentTypes": true
}

Update List

POST /_api/web/lists/getbytitle('Documents') Headers: X-HTTP-Method: MERGE, IF-MATCH: *

Request Body:

{
  "__metadata": { "type": "SP.List" },
  "Description": "Updated description"
}

Delete List

DELETE /_api/web/lists/getbytitle('Documents') Headers: IF-MATCH: *


List Item Operations

Get List Items

GET /_api/web/lists/getbytitle('Documents')/items

Returns all items in a list.

Response:

{
  "d": {
    "results": [
      {
        "__metadata": { "type": "SP.Data.DocumentsItem" },
        "Id": 1,
        "Title": "Document 1",
        "FileLeafRef": "document1.docx",
        "Modified": "2025-11-15T10:00:00Z",
        "Created": "2025-11-01T10:00:00Z",
        "Author": { "Title": "John Doe" }
      }
    ]
  }
}

Get Item by ID

GET /_api/web/lists/getbytitle('Documents')/items(1)

Returns a specific item by ID.

Create Item

POST /_api/web/lists/getbytitle('Documents')/items

Request Body:

{
  "__metadata": { "type": "SP.Data.DocumentsItem" },
  "Title": "New Document",
  "FileLeafRef": "newdoc.docx"
}

Update Item

POST /_api/web/lists/getbytitle('Documents')/items(1) Headers: X-HTTP-Method: MERGE, IF-MATCH: *

Request Body:

{
  "__metadata": { "type": "SP.Data.DocumentsItem" },
  "Title": "Updated Title"
}

Delete Item

DELETE /_api/web/lists/getbytitle('Documents')/items(1) Headers: IF-MATCH: *


File Operations

Get File Metadata

GET /_api/web/getfilebyserverrelativeurl('/Shared Documents/file.docx')

Returns file metadata.

Response:

{
  "d": {
    "__metadata": { "type": "SP.File" },
    "Name": "file.docx",
    "ServerRelativeUrl": "/Shared Documents/file.docx",
    "Length": 12345,
    "TimeCreated": "2025-11-01T10:00:00Z",
    "TimeLastModified": "2025-11-15T10:00:00Z",
    "Title": "My Document"
  }
}

Download File

GET /_api/web/getfilebyserverrelativeurl('/Shared Documents/file.docx')/$value

Returns the file content as binary stream.

Upload File

POST /_api/web/getfolderbyserverrelativeurl('/Shared Documents')/files/add(url='newfile.docx',overwrite=true) Headers: Content-Type: application/octet-stream

Body: Binary file content

Delete File

DELETE /_api/web/getfilebyserverrelativeurl('/Shared Documents/file.docx') Headers: IF-MATCH: *

Check Out File

POST /_api/web/getfilebyserverrelativeurl('/Shared Documents/file.docx')/checkout

Check In File

POST /_api/web/getfilebyserverrelativeurl('/Shared Documents/file.docx')/checkin(comment='My changes',checkintype=1)

checkintype values: - 0 = MinorCheckIn - 1 = MajorCheckIn - 2 = OverwriteCheckIn

Undo Check Out

POST /_api/web/getfilebyserverrelativeurl('/Shared Documents/file.docx')/undocheckout


Folder Operations

Get Folder Metadata

GET /_api/web/getfolderbyserverrelativeurl('/Shared Documents/Subfolder')

Get Folder Files

GET /_api/web/getfolderbyserverrelativeurl('/Shared Documents')/files

Get Subfolders

GET /_api/web/getfolderbyserverrelativeurl('/Shared Documents')/folders

Create Folder

POST /_api/web/folders

Request Body:

{
  "__metadata": { "type": "SP.Folder" },
  "ServerRelativeUrl": "/Shared Documents/New Folder"
}

Delete Folder

DELETE /_api/web/getfolderbyserverrelativeurl('/Shared Documents/Folder') Headers: IF-MATCH: *


OData Query Support

$select (Field Selection)

Select specific fields to return:

GET /_api/web/lists?$select=Title,ItemCount

Response:

{
  "d": {
    "results": [
      { "Title": "Documents", "ItemCount": 10 },
      { "Title": "Tasks", "ItemCount": 5 }
    ]
  }
}

$filter (Filtering)

Filter results based on criteria:

GET /_api/web/lists?$filter=Hidden eq false and ItemCount gt 5

Supported Operators: - Comparison: eq, ne, gt, ge, lt, le - Logical: and, or, not - String: startswith, endswith, substringof

Examples:

# Equals
$filter=Title eq 'Documents'

# Not equals
$filter=Hidden ne true

# Greater than
$filter=ItemCount gt 10

# Starts with
$filter=startswith(Title,'Doc')

# Contains (substring)
$filter=substringof('test',Title)

# Multiple conditions
$filter=Hidden eq false and ItemCount gt 5

$orderby (Sorting)

Sort results:

GET /_api/web/lists?$orderby=Title asc
GET /_api/web/lists?$orderby=ItemCount desc
GET /_api/web/lists?$orderby=Title asc,ItemCount desc

$top (Limit Results)

Limit number of results:

GET /_api/web/lists?$top=10

$skip (Pagination)

Skip results (for pagination):

GET /_api/web/lists?$skip=20&$top=10

Expand related entities:

GET /_api/web?$expand=Lists
GET /_api/web/lists?$expand=Fields
GET /_api/web/lists/getbytitle('Documents')/items?$expand=Author,Editor

Combined Queries

Combine multiple query parameters:

GET /_api/web/lists/getbytitle('Documents')/items?$select=Title,Created&$filter=Created gt datetime'2025-01-01T00:00:00Z'&$orderby=Created desc&$top=10

User & Group Operations

Get Site Users

GET /_api/web/siteusers

Get User by ID

GET /_api/web/siteusers/getbyid(1)

Get User by Email

GET /_api/web/siteusers/getbyemail('user@domain.com')

Ensure User

POST /_api/web/ensureuser

Request Body:

{
  "logonName": "i:0#.w|domain\\user"
}

Get Site Groups

GET /_api/web/sitegroups

Get Group by ID

GET /_api/web/sitegroups/getbyid(5)

Create Group

POST /_api/web/sitegroups

Request Body:

{
  "__metadata": { "type": "SP.Group" },
  "Title": "New Group",
  "Description": "Group description"
}

Add User to Group

POST /_api/web/sitegroups/getbyid(5)/users

Request Body:

{
  "__metadata": { "type": "SP.User" },
  "LoginName": "i:0#.w|domain\\user"
}


Search Operations

Execute Search Query

GET /_api/search/query?querytext='test'

Query Parameters: - querytext: Search query - rowlimit: Max results (default: 500) - startrow: Start row for pagination - selectproperties: Fields to return - refiners: Facet refinement

Response:

{
  "d": {
    "query": {
      "PrimaryQueryResult": {
        "RelevantResults": {
          "RowCount": 2,
          "TotalRows": 2,
          "Table": {
            "Rows": {
              "results": [
                {
                  "Cells": {
                    "results": [
                      { "Key": "Title", "Value": "Document 1" },
                      { "Key": "Path", "Value": "/Shared Documents/doc1.docx" }
                    ]
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}


Limitations & Workarounds

❌ Not Supported

OData v4 Features: - $count=true (use OData v3 __count instead) - $search (use $filter with substringof) - $apply (use multiple queries)

Advanced Features: - Workflow REST APIs (deprecated in SharePoint) - Social feed APIs (use Microsoft Graph instead) - SharePoint Online-specific endpoints (Hub Sites, Compliance)

⚠️ Partial Support

Batch Requests: - $batch endpoint exists but has limited testing - Prefer individual requests for reliability

Navigation Properties: - Some complex $expand paths may not work - Use multiple requests if expansion fails

✅ Workarounds

Missing OData Features → Use SOAP:

# If REST query fails, use SOAP Lists service:
$svc = New-WebServiceProxy -Uri "http://localhost:5000/_vti_bin/lists.asmx?WSDL"
$items = $svc.GetListItems("Documents", $query, $viewFields, ...)

Complex Queries → Break into Multiple Requests:

// Instead of complex $expand:
const lists = await fetch('/_api/web/lists').then(r => r.json());
const items = await Promise.all(
  lists.d.results.map(list =>
    fetch(`/_api/web/lists(guid'${list.Id}')/items`).then(r => r.json())
  )
);


Error Handling

Error Response Format

{
  "error": {
    "code": "-1, System.ArgumentException",
    "message": {
      "lang": "en-US",
      "value": "List 'InvalidList' does not exist at site with URL 'http://localhost:5000'."
    }
  }
}

Common HTTP Status Codes

Code Meaning Common Cause
200 OK Request succeeded
201 Created Resource created successfully
400 Bad Request Invalid request body or query
401 Unauthorized Missing or invalid authentication
404 Not Found List, item, or file not found
409 Conflict Resource already exists (create)
412 Precondition Failed IF-MATCH etag mismatch
500 Internal Server Error Server error (check logs)

Best Practices

1. Use $select for Better Performance

Only request fields you need:

// ❌ Bad - returns all fields
fetch('/_api/web/lists/getbytitle("Documents")/items')

// ✅ Good - only returns needed fields
fetch('/_api/web/lists/getbytitle("Documents")/items?$select=Title,Created')

2. Use Batch Requests for Multiple Operations

Reduce round-trips with batch requests:

POST /_api/$batch
Content-Type: multipart/mixed; boundary=batch_abc123

--batch_abc123
Content-Type: application/http
Content-Transfer-Encoding: binary

GET /_api/web/lists HTTP/1.1
Accept: application/json

--batch_abc123--

3. Handle Pagination for Large Results

Use $top and $skip for pagination:

async function getAllItems(listTitle) {
  const pageSize = 100;
  let skip = 0;
  let allItems = [];

  while (true) {
    const url = `/_api/web/lists/getbytitle('${listTitle}')/items?$top=${pageSize}&$skip=${skip}`;
    const response = await fetch(url).then(r => r.json());
    const items = response.d.results;

    if (items.length === 0) break;

    allItems.push(...items);
    skip += pageSize;
  }

  return allItems;
}

4. Cache Form Digest

Cache form digest to avoid unnecessary requests:

let formDigestValue = null;
let formDigestExpiry = null;

async function getFormDigest() {
  if (formDigestValue && formDigestExpiry > Date.now()) {
    return formDigestValue;
  }

  const response = await fetch('/_api/contextinfo', { method: 'POST' })
    .then(r => r.json());

  formDigestValue = response.d.GetContextWebInformation.FormDigestValue;
  formDigestExpiry = Date.now() + 1800000; // 30 minutes

  return formDigestValue;
}

See Also


Last Updated: November 15, 2025 API Version: OData v3 Compatibility: SharePoint 2019, SharePoint Online

Navigation: Home | Documentation | Features | REST API