Overview
Each credential belongs to one project and is created by an owner or admin in Project settings › API. It has a public client ID, a client secret shown only once, and a list of permissions chosen per module.
Your server exchanges the credential for a short-lived access token and sends it on every request. The API is read-only: no endpoint creates, changes or deletes data.
Authentication
OAuth 2.0 client credentials
Token lifetime
1 hour, no refresh token
Access
Read-only, one project per credential
Base URL: https://api.wayki.app
Authentication
We use the OAuth 2.0 client-credentials flow (RFC 6749 §4.4). The secret only travels to the token endpoint; every data request carries a token that expires on its own.
1. Create a credential
In Wayki, open the project › Settings › API › New credential. Pick only the permissions you need and, when you can, restrict by IP and set an expiry date. Copy the client secret: it will not be shown again. If you don't see the API tab, ask Wayki to enable the API module for your project.
2. Request a token
Send client_id and client_secret with HTTP Basic (recommended) or in the body, with grant_type=client_credentials. Optionally ask for fewer permissions with scope.
3. Call the API
Send the token in the Authorization: Bearer header. Reuse it until shortly before expires_in, then request another.
curl -X POST https://api.wayki.app/v1/oauth/token -u 'CLIENT_ID:CLIENT_SECRET' -d grant_type=client_credentials
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "issues:read rfis:read"
}
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/issues?page=1&limit=50' -H 'Authorization: Bearer ACCESS_TOKEN'
{
"data": [
{ "_id": "66f1…", "issueNumber": 128, "title": "Fisura en losa N3", "statusKey": "open", … }
],
"meta": { "page": 1, "limit": 50, "total": 312, "totalPages": 7 }
}
Node.js (with token caching)
const BASE = "https://api.wayki.app";
const PROJECT = process.env.WAYKI_PROJECT_ID;
let cached = { token: null, expiresAt: 0 };
async function getToken() {
// Reuse the token until one minute before it expires.
if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;
const basic = Buffer.from(
`${process.env.WAYKI_CLIENT_ID}:${process.env.WAYKI_CLIENT_SECRET}`,
).toString("base64");
const res = await fetch(`${BASE}/v1/oauth/token`, {
method: "POST",
headers: {
Authorization: `Basic ${basic}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: "grant_type=client_credentials",
});
if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
const body = await res.json();
cached = { token: body.access_token, expiresAt: Date.now() + body.expires_in * 1000 };
return cached.token;
}
async function listAllRfis() {
const all = [];
for (let page = 1; ; page++) {
const res = await fetch(
`${BASE}/v1/projects/${PROJECT}/rfis?page=${page}&limit=100`,
{ headers: { Authorization: `Bearer ${await getToken()}` } },
);
if (!res.ok) throw new Error(`RFIs request failed: ${res.status}`);
const { data, meta } = await res.json();
all.push(...data);
if (page >= meta.totalPages) return all;
}
}
import os, requests
BASE = "https://api.wayki.app"
token = requests.post(
f"{BASE}/v1/oauth/token",
auth=(os.environ["WAYKI_CLIENT_ID"], os.environ["WAYKI_CLIENT_SECRET"]),
data={"grant_type": "client_credentials", "scope": "meetings:read"},
timeout=10,
).json()["access_token"]
meetings = requests.get(
f"{BASE}/v1/projects/{os.environ['WAYKI_PROJECT_ID']}/meetings",
headers={"Authorization": f"Bearer {token}"},
params={"from": "2026-09-01", "to": "2026-09-30"},
timeout=10,
).json()["data"]
- Replace CLIENT_ID, CLIENT_SECRET and ACCESS_TOKEN with your values. Commands are one line and work the same in bash and PowerShell; in Windows PowerShell 5.1 type curl.exe instead of curl.
- There is no refresh token: when the token expires, request a new one with the credential.
- The token only works for the credential's project. Another projectId answers 403.
- Revoking the credential, rotating its secret, removing a permission or archiving the project cuts live tokens off immediately.
- The token endpoint allows 10 requests per minute per IP: keep the token in memory instead of requesting one per call.
Reference
Every route starts with /v1/projects/{projectId}. The downloadable OpenAPI describes the same endpoints.
Project and members
Permission: project:read · members:readGeneral project data and the member list with roles.
- GET
/v1/projects/{projectId}The project (project:read). - GET
/v1/projects/{projectId}/membersMembers and roles, not paged (members:read).
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6' -H 'Authorization: Bearer ACCESS_TOKEN'
Issues
Permission: issues:readPaged list, detail, replies and settings (statuses, priorities, types) of issues.
- GET
/v1/projects/{projectId}/issuesPaged list. - GET
/v1/projects/{projectId}/issues/{issueId}Detail. - GET
/v1/projects/{projectId}/issues/{issueId}/repliesReplies, oldest first (order=desc reverses). - GET
/v1/projects/{projectId}/issues/settingsModule settings: catalogs to interpret the fields.
Allowed sort: createdAt, updatedAt, number, title, dueDate, priority. from / to filter on creation date.
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/issues?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'
RFIs
Permission: rfis:readPaged list, detail, replies and settings (statuses, priorities, types) of RFIs.
- GET
/v1/projects/{projectId}/rfisPaged list. - GET
/v1/projects/{projectId}/rfis/{rfiId}Detail. - GET
/v1/projects/{projectId}/rfis/{rfiId}/repliesReplies, oldest first (order=desc reverses). - GET
/v1/projects/{projectId}/rfis/settingsModule settings: catalogs to interpret the fields.
Allowed sort: createdAt, updatedAt, number, title, dueDate, status, priority. from / to filter on creation date.
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/rfis?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'
Change orders
Permission: change-orders:readPaged list, detail, replies and settings (statuses, priorities, types) of change orders.
- GET
/v1/projects/{projectId}/change-ordersPaged list. - GET
/v1/projects/{projectId}/change-orders/{changeOrderId}Detail. - GET
/v1/projects/{projectId}/change-orders/{changeOrderId}/repliesReplies, oldest first (order=desc reverses). - GET
/v1/projects/{projectId}/change-orders/settingsModule settings: catalogs to interpret the fields.
Allowed sort: createdAt, updatedAt, number, title, dueDate, status, priority. from / to filter on creation date.
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/change-orders?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'
Non-conformances
Permission: non-conformances:readPaged list, detail, replies and settings (statuses, priorities, types) of non-conformances.
- GET
/v1/projects/{projectId}/non-conformancesPaged list. - GET
/v1/projects/{projectId}/non-conformances/{nonConformanceId}Detail. - GET
/v1/projects/{projectId}/non-conformances/{nonConformanceId}/repliesReplies, oldest first (order=desc reverses). - GET
/v1/projects/{projectId}/non-conformances/settingsModule settings: catalogs to interpret the fields.
Allowed sort: createdAt, updatedAt, number, title, dueDate, status, priority. from / to filter on creation date.
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/non-conformances?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'
Meetings
Permission: meetings:readMeetings with agenda, participants and agreements, plus the frozen minutes of each closed session.
- GET
/v1/projects/{projectId}/meetingsPaged list. - GET
/v1/projects/{projectId}/meetings/{meetingId}Detail with agreements and participants. - GET
/v1/projects/{projectId}/meetings/{meetingId}/minutesFrozen minutes (one per closed session). - GET
/v1/projects/{projectId}/meetings/{meetingId}/minutes/{versionId}One set of minutes. - GET
/v1/projects/{projectId}/meetings/settingsAgreement statuses and priorities.
Allowed sort: startPlannedDate, createdAt, title, number. from / to filter on the planned start date.
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/meetings?from=2026-09-01&to=2026-09-30' -H 'Authorization: Bearer ACCESS_TOKEN'
Forms
Permission: forms:readFilled-in forms (inspections, checklists, permits) and their settings.
- GET
/v1/projects/{projectId}/formsPaged list. - GET
/v1/projects/{projectId}/forms/{formId}Detail. - GET
/v1/projects/{projectId}/forms/settingsStatuses, priorities and types.
Allowed sort: createdAt, updatedAt, number, name. from / to filter on creation date.
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/forms?q=concreto' -H 'Authorization: Bearer ACCESS_TOKEN'