Public endpoints
Endpoints anyone can call without signing in: HTTP functions, public forms, booking pages, calendar feeds and invitations.
Some AxisIQ features can be used by people who have no account and no key: a visitor submits a form, your website reads a published page, a customer books a meeting, a webhook calls a function. These public endpoints live at the root of https://axisiq.co, not under /api/v1.
How public access works
Nothing is public until you open it. Each public endpoint answers 404 NOT_FOUND for anything that does not exist or that you have not made public, so a visitor learns nothing about what is behind it.
Public access is granted through a role for visitors who are not signed in:
- Open Team & Permissions › Roles and create a role.
- Turn on Use for visitors who are not signed in (the role then shows a Public visitors badge). It is not given to any person: it applies to every anonymous request.
- Grant it only what you want the public to reach:
- To publish a form:
forms:readandforms:submiton that form. - To serve website content:
content:deliveron the site (and onassetsfor images). - To let an HTTP function touch data: the specific permissions it needs. With no such grant a function can still compute, but it cannot read or write anything.
- To publish a form:
You can pick these in the role editor, or write them as rules under Advanced rules (see Policy format). Booking pages and subscription links are different: they work from their own switches and secret links, with no visitor role needed.
Rate limits are per IP address: see Conventions.
Endpoints
| Method | Path | What it does |
|---|---|---|
GET · POST |
/fn/{orgId}/{functionId} |
Run an HTTP-enabled function |
GET |
/forms/{orgId}/{formKey} |
A published form's definition |
POST |
/forms/{orgId}/{formKey} |
Submit a published form |
GET |
/content/{orgId}/{siteKey}/… |
Published website content. See Content delivery |
GET |
/cal/{orgId}/book/{calendarKey} |
A booking page's details |
GET |
/cal/{orgId}/book/{calendarKey}/slots |
Free times |
POST |
/cal/{orgId}/book/{calendarKey} |
Book a time |
GET |
/cal/{orgId}/feed/{token} |
A calendar's subscription feed (.ics) |
GET · POST |
/cal/{orgId}/rsvp/{token} |
See and answer an invitation |
GET |
/cal/{orgId}/rsvp/{token}/ics |
Add an invitation to a calendar app |
HTTP functions
Turn on Expose over HTTP on a function (in Functions) and use Copy public URL:
https://axisiq.co/fn/{orgId}/{functionId}
Call it with GET or POST. The function runs and its return value is the response. The response is not wrapped in {"data": …}.
The function receives one argument describing the request:
{
"method": "POST",
"path": "/fn/0190f0aa-…/0190f0ee-…",
"query": { "ref": "abc" },
"body": { "name": "Asha" }
}
query holds the first value of each query parameter. body is the parsed JSON when the request body is JSON, otherwise the raw text, and null when there is none.
function handler(event) {
return { hello: event.body.name, via: event.method };
}
curl -s -X POST https://axisiq.co/fn/$ORG/$FN -H "Content-Type: application/json" -d '{"name": "Asha"}'
{ "hello": "Asha", "via": "POST" }
| Status | When |
|---|---|
| 200 | The function returned. The body is its return value as JSON (application/json) |
| 404 | The function does not exist, is disabled, or is not exposed over HTTP. All read the same |
| 429 | More than 60 requests per minute from this IP address |
| 500 | The function threw or timed out. The body is {"error": {"code": "INTERNAL", "message": "function failed"}} (or "function timed out"). The detail is kept private, because it could contain your data |
The function runs with the permissions of the visitor role, and can use everything in the Functions SDK that role allows. Anyone on the internet can call the URL, so validate the input and never return anything you would not want public.
Public forms
Open a form to the web by publishing it and granting the visitor role forms:read and forms:submit on it (see above). The form builder's Share tab then gives you a Public link (https://axisiq.co/f/{orgId}/{formKey}, a ready-made page) and an Embed in your site snippet. To build your own page, use the endpoints.
GET /forms/{orgId}/{formKey}
{
"data": {
"key": "contact-us",
"name": "Contact us",
"description": "Ask us anything",
"fields": [
{ "key": "name", "label": "Your name", "type": "string", "required": true },
{ "key": "email", "label": "Email", "type": "email", "required": true },
{ "key": "message", "label": "Message", "type": "text" }
],
"settings": { "submit_label": "Send", "success_message": "Thanks, we will be in touch." }
}
}
The form's targets (which record or function it feeds) are never revealed. The response may be cached for 60 seconds. Draw each field by its type and rules (see Record types and fields).
POST /forms/{orgId}/{formKey}
curl -s -X POST https://axisiq.co/forms/$ORG/contact-us \
-H "Content-Type: application/json" \
-d '{"values": {"name": "Asha", "email": "asha@example.com", "message": "Hello"}}'
{ "data": { "ok": true, "message": "Thanks, we will be in touch.", "redirect": "" } }
Status 201. If the form defines a redirect, send the visitor there.
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR |
A value is missing or invalid. The message names the field, so show it to the visitor |
| 404 | NOT_FOUND |
No such form, it is not published, or the visitor role does not allow it |
| 429 | RATE_LIMITED |
More than 30 submissions per minute from this IP address |
A submission is always kept, even if a follow-up step fails afterwards. The visitor only ever learns that it worked.
Note: Browsers on other websites cannot call the form endpoints directly. Use the hosted page, the embed snippet, or post from your own server.
Booking pages
In Calendar, open a calendar's settings, then Booking page, and switch on Let people book time on this calendar. The Booking link (https://axisiq.co/book/{orgId}/{calendarKey}) is the ready-made page. To build your own, use:
GET /cal/{orgId}/book/{calendarKey}
{
"data": {
"title": "Book a call",
"description": "",
"durations": [30, 60],
"timezone": "Asia/Kolkata",
"location": "Google Meet",
"horizon_days": 30,
"hours": { "mon": [["09:00", "17:00"]] },
"owner_name": "Asha Rao",
"org_name": "Example Ltd",
"color": "teal"
}
}
GET /cal/{orgId}/book/{calendarKey}/slots
| Parameter | Notes |
|---|---|
from, to |
Required. RFC 3339 or YYYY-MM-DD |
duration |
Minutes. One of the page's durations. The first if omitted |
Returns { "data": { "slots": [ "2026-10-07T04:30:00Z", … ] } }, the start times that are free.
POST /cal/{orgId}/book/{calendarKey}
| Field | Type | Required | Notes |
|---|---|---|---|
start |
string | Yes | One of the slots |
duration |
number | No | Minutes |
name |
string | Yes | The booker |
email |
string | Yes | Where the confirmation goes |
notes |
string | No |
Response 201: { "data": { "ok": true, "start": "…", "end": "…", "token": "…" } }. The token opens the booker's own page to see, change or cancel the booking. A confirmation email is sent, with limits per workspace and per recipient per day; a booking still stands when the email is skipped. If someone took the time first the answer is 409 SLOT_TAKEN: show the times again.
Calendar subscription feed
Subscribe & import in the calendar's settings produces a secret link:
https://axisiq.co/cal/{orgId}/feed/{token}.ics
Add it to Google Calendar, Apple Calendar or Outlook. Anyone with the link can read the calendar, so treat it like a password. Turning the link off (or on again) in the settings issues a new one and the old one stops working.
Invitations (RSVP)
Guests invited by email receive a link containing a token:
GET /cal/{orgId}/rsvp/{token}returns the invitation:title,description,location,start,end,all_day,timezone,when(a readable time),recurring,cancelled,organizer,org_name,guest_name,guest_email,statusandbooking(true when it came from a booking page).POST /cal/{orgId}/rsvp/{token}with{ "status": "accepted" }(ordeclined,tentative) records the answer and returns the same object. A booker who declines cancels the booking.GET /cal/{orgId}/rsvp/{token}/icsdownloads the event as.ics.
Provider callbacks and unsubscribe pages
Payment and messaging providers report back to AxisIQ through webhook addresses. These are not for your code to call. When you connect a provider in Invoices & Payments or Messaging, the connection shows its webhook address and where to paste it in the provider's dashboard.
Messages can link recipients to an unsubscribe page. Opening it shows a confirmation; confirming adds the address to the do-not-contact list described in Messaging.