Skip to Content
DocsAPI ReferenceREST API

REST API Reference

The Ycode public v1 API gives programmatic access to collections, items, forms, and submissions, plus visitor analytics on Ycode Cloud. Use it to build custom integrations, sync data from other systems, or power external applications.

Base URL

https://yoursite.ycode.website/ycode/api/v1

Use your project’s own domain: its ycode.website subdomain or a custom domain on Ycode Cloud, or your server’s domain when self-hosting.

Authentication

Every request needs an API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Generate keys in the builder under Integrations → Ycode API. See API keys for details.

Request Format

  • Send request bodies as JSON with Content-Type: application/json
  • All responses are JSON

Errors

Errors return an HTTP status code and a JSON body with a message and a code:

{ "error": "Item not found", "code": "NOT_FOUND" }
StatusCodeMeaning
400INVALID_REQUESTThe request body or parameters are invalid
401UNAUTHORIZEDThe API key is missing or invalid
403FORBIDDENThe project is suspended (Ycode Cloud); only reads are allowed
404NOT_FOUNDThe collection, item, form, or submission does not exist
500INTERNAL_ERRORSomething went wrong on the server

Collections

MethodEndpointDescription
GET/collectionsList all collections
GET/collections/:idGet a collection and its fields
GET/collections/:id/itemsList items
GET/collections/:id/items/:itemIdGet an item
POST/collections/:id/itemsCreate an item
PUT/collections/:id/items/:itemIdReplace an item
PATCH/collections/:id/items/:itemIdUpdate some fields of an item
DELETE/collections/:id/items/:itemIdDelete an item

The API works with published collections and items: what visitors see on the live site. A collection or field that has never been published is not available yet.

Writes take effect on the live site immediately, with no publish step, and update the CMS in the builder at the same time. Pages that show the collection are refreshed automatically.

List Collections

GET /ycode/api/v1/collections
{ "collections": [ { "id": "5f0c…", "displayName": "Blog Posts", "singularName": "Blog Post", "slug": "blog-posts" } ] }

Get Collection

GET /ycode/api/v1/collections/:id

Returns the collection with its fields. Use the field slug values as keys when filtering, sorting, and writing items. isRequired is true for fields you can write and false for fields Ycode sets automatically (ID, Created Date, Updated Date).

{ "id": "5f0c…", "displayName": "Blog Posts", "singularName": "Blog Post", "slug": "blog-posts", "fields": [ { "id": "e5f6…", "displayName": "ID", "slug": "id", "type": "number", "isRequired": false }, { "id": "a1b2…", "displayName": "Name", "slug": "name", "type": "text", "isRequired": true }, { "id": "c3d4…", "displayName": "Read Time", "slug": "read-time", "type": "number", "isRequired": true } ] }

Item Format

Items are returned as flat objects keyed by field display name, plus an _id:

{ "_id": "f299…", "ID": 3, "Name": "Hello world", "Slug": "hello-world", "Created Date": "2026-11-09T08:44:25.257Z", "Updated Date": "2026-11-09T08:44:28.355Z", "Read Time": 4, "Author": { "_id": "9a8b…", "Name": "Jane Doe" } }
  • _id is the item’s unique identifier. Use it in item URLs (:itemId) and as the value of reference fields.
  • ID is the item’s sequential number in the collection.
  • Fields without a value are left out.
  • Reference fields are expanded into the referenced item, and multi-reference fields into an array of items, up to 6 levels deep.

List Items

GET /ycode/api/v1/collections/:id/items
ParameterDescription
pagePage number. Default 1
per_pageItems per page. Default 100, max 1000
limitReturn at most this many items (max 1000), instead of per_page
sort_byField slug to sort by
order_byasc (default) or desc, used with sort_by
filter[field_slug]Only return items whose field exactly equals this value. Repeat for several fields
fields[Collection Name]Comma-separated display names of the fields to return. Use fields[Collection Name.Reference Field] to limit the fields of expanded references

Field slugs are matched case-insensitively. Unknown slugs in sort_by and filter are ignored.

curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://yoursite.ycode.website/ycode/api/v1/collections/:id/items?sort_by=read-time&order_by=desc&filter[category]=news&per_page=50"
{ "items": [ { "_id": "f299…", "ID": 3, "Name": "Hello world", "Slug": "hello-world" } ], "pagination": { "page": 1, "per_page": 50, "total": 12 } }

Get Item

GET /ycode/api/v1/collections/:id/items/:itemId

Returns one item in the item format. Deleted items return 404.

Writing Field Values

POST, PUT, and PATCH take a JSON object with field values directly at the top level (no wrapper):

{ "name": "Hello world", "slug": "hello-world", "read-time": 4 }
  • Use each field’s slug from Get Collection as the key; matching is case-insensitive.
  • Keys that don’t match a field are ignored without an error, so check the slug if a value doesn’t change.
  • Values are stored as text. Numbers and booleans can be sent as JSON values or strings.
  • For a reference field, send the referenced item’s _id. For a multi-reference field, send a JSON-encoded array of _id values as a string, for example "[\"9a8b…\",\"7c6d…\"]".
  • ID, Created Date, and Updated Date are set automatically and can’t be written. Updated Date is refreshed on every update.

Create Item

POST /ycode/api/v1/collections/:id/items

Creates an item and publishes it immediately. Returns the new item with status 201.

curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Hello world", "slug": "hello-world", "read-time": 4}' \ "https://yoursite.ycode.website/ycode/api/v1/collections/:id/items"

Update Item (Partial)

PATCH /ycode/api/v1/collections/:id/items/:itemId

Updates only the fields in the request body and leaves every other field unchanged. This is the endpoint to use for recurring updates, such as refreshing a value every few minutes. Returns the updated item.

curl -X PATCH \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"temperature": "21.5"}' \ "https://yoursite.ycode.website/ycode/api/v1/collections/:id/items/:itemId"

Replace Item

PUT /ycode/api/v1/collections/:id/items/:itemId

Replaces the item’s values. Every writable field that is not in the request body, including Name and Slug, is cleared. Use PATCH unless you mean to overwrite the whole item. Returns the updated item.

curl -X PUT \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Hello again", "slug": "hello-again", "read-time": 5}' \ "https://yoursite.ycode.website/ycode/api/v1/collections/:id/items/:itemId"

Delete Item

DELETE /ycode/api/v1/collections/:id/items/:itemId

Removes the item from the live site and the CMS.

curl -X DELETE \ -H "Authorization: Bearer YOUR_API_KEY" \ "https://yoursite.ycode.website/ycode/api/v1/collections/:id/items/:itemId"
{ "deleted": true, "_id": "f299…" }

Forms

MethodEndpointDescription
GET/formsList forms
GET/forms/:formIdGet a form’s submission counts
GET/forms/:formId/submissionsList submissions
POST/forms/:formId/submissionsCreate a submission
GET/forms/:formId/submissions/:submissionIdGet a submission
PATCH/forms/:formId/submissions/:submissionIdChange a submission’s status
DELETE/forms/:formId/submissions/:submissionIdDelete a submission

:formId is the form’s ID (for example contact-form), as returned by List Forms. Forms are listed from their submissions, so a form appears in the API once it has at least one.

Submission Format

{ "id": "8c7b…", "formId": "contact-form", "payload": { "name": "Jane", "email": "jane@example.com", "message": "Hello!" }, "metadata": { "source": "api", "user_agent": "curl/8.7.1" }, "status": "new", "createdAt": "2026-11-09T08:45:25.497Z" }

status is one of new, read, archived, or spam.

List Forms

GET /ycode/api/v1/forms
{ "forms": [ { "id": "contact-form", "submissionCount": 42, "newCount": 5, "latestSubmission": "2026-11-09T08:45:25.497Z" } ] }

Get Form

GET /ycode/api/v1/forms/:formId
{ "id": "contact-form", "submissionCount": 42, "statusCounts": { "new": 5, "read": 30, "archived": 7, "spam": 0 }, "latestSubmission": "2026-11-09T08:45:25.497Z" }

List Submissions

GET /ycode/api/v1/forms/:formId/submissions
ParameterDescription
pagePage number. Default 1
per_pageSubmissions per page. Default 50, max 100
statusOnly return submissions with this status
{ "submissions": [ { "id": "8c7b…", "formId": "contact-form", "payload": { … }, "status": "new", … } ], "pagination": { "page": 1, "perPage": 50, "total": 42 } }

Create Submission

POST /ycode/api/v1/forms/:formId/submissions

Send the submitted fields inside payload. metadata is optional; source: "api" and the request’s user agent are added to it automatically. Returns the new submission with status 201.

curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"payload": {"name": "Jane", "email": "jane@example.com", "message": "Hello!"}, "metadata": {"page_url": "/contact"}}' \ "https://yoursite.ycode.website/ycode/api/v1/forms/contact-form/submissions"

Submissions created through the API are only stored: they don’t send email notifications, run apps, or trigger webhooks.

Get Submission

GET /ycode/api/v1/forms/:formId/submissions/:submissionId

Returns one submission in the submission format.

Update Submission Status

PATCH /ycode/api/v1/forms/:formId/submissions/:submissionId
curl -X PATCH \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status": "read"}' \ "https://yoursite.ycode.website/ycode/api/v1/forms/contact-form/submissions/:submissionId"

Only status can be changed. Returns the updated submission.

Delete Submission

DELETE /ycode/api/v1/forms/:formId/submissions/:submissionId

Deletes the submission and returns 204 No Content.

Analytics

Analytics is available on Ycode Cloud only. On self-hosted Ycode this endpoint returns 404.

MethodEndpointDescription
GET/analyticsVisitor analytics for the published site
GET /ycode/api/v1/analytics
ParameterDescription
periodtoday, yesterday, 7d, 30d, 90d, or 12m. Defaults to 30d
from, toA custom range as YYYY-MM-DD, inclusive. Send both; they override period
breakdownsComma-separated top-10 lists, up to 5. Defaults to page,referrer
pathOnly count views of this page path, for example /pricing

Available breakdowns: page, entry_page, exit_page, referrer, utm_source, utm_medium, utm_campaign, country, device, browser, os, item (CMS items), and event (tracked clicks and form submissions).

curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://yoursite.ycode.website/ycode/api/v1/analytics?period=7d&breakdowns=page,country"
{ "from": "2026-11-05", "to": "2026-11-11", "timezone": "UTC", "historyDays": 90, "clamped": false, "visitors": 1240, "pageviews": 3815, "visits": 1592, "bounceRate": 0.42, "avgVisitSeconds": 96, "liveVisitors": 7, "interval": "day", "series": [ { "start": "2026-11-05", "visitors": 168, "pageviews": 512 } ], "breakdowns": [ { "dimension": "page", "rows": [ { "label": "/", "visitors": 812, "total": 1430 } ] } ] }
  • Days are in UTC.
  • bounceRate is a share from 0 to 1. bounceRate and avgVisitSeconds are null when there were no visits.
  • liveVisitors counts visitors in the last 5 minutes.
  • interval is day, week, or month, depending on the length of the range.
  • In breakdown rows, total is pageviews; visits for entry_page and exit_page; and events for event.
  • The range is shortened to the plan’s history window. When that happens, clamped is true and historyDays shows the window.

Invalid parameters return 400 with code VALIDATION_ERROR.

Last updated on