WindKeep API Specification
This document provides comprehensive documentation for the WindKeep REST API, which is used by the WindKeep web application and CLI to manage organizations, projects, secrets, and user profiles. The WindKeep API is organized around REST principles with predictable resource-oriented URLs, JSON request/response bodies, and standard HTTP response codes.
Overview
Authentication
The API uses OAuth 2.0 for user authentication via third-party providers (Google, GitHub and GitLab). Sessions are managed using secure HTTP-only cookies.
For CLI and programmatic access, an API token is used for authentication. The token can be obtained from the preferences page. Include the token in the Authorization header:
Authorization: Bearer YOUR_API_TOKEN
Response Format
All responses are returned in JSON format. Successful responses return a 2xx status code. Error responses include an error message in the response body.
Error Handling
The API uses standard HTTP response codes to indicate success or failure:
200 OK- Request succeeded400 Bad Request- Invalid request parameters or validation error401 Unauthorized- Authentication required or invalid credentials403 Forbidden- Insufficient permissions404 Not Found- Resource not found409 Conflict- Resource conflict500 Internal Server Error- Server error
Endpoints
Authentication
Login with Provider
POST
/api/auth/{provider}
Initiates OAuth login with the specified provider.
Route Parameters:
provider: OAuth provider name (required). Supported providers:google,github,gitlab.
Response:
Navigates to the provider's OAuth consent screen.
Logout
POST
/api/auth/logout
Logs out the authenticated user and clears the session.
Response:
{
"success": true
}
Refresh Session
POST
/api/auth/refresh
Refreshes the authenticated user's session, extending it by 7 days.
Response:
{
"success": true,
"expiresAt": "Date"
}
Validate Session
POST
/api/auth/validate
Validates the authenticated user's session and checks for inactivity timeout. Updates the last activity timestamp.
Response:
{
"valid": true,
"expiresAt": "Date"
}
User Profile
Get User Profile
GET
/api/user
Retrieves the authenticated user's profile information, including organization and project memberships.
Response:
{
"userData": {
"id": "string",
"email": "string",
"name": "string",
"image": "string | null",
"apiToken": "string | null",
"createdAt": "Date",
"updatedAt": "Date",
"orgMemberships": [
{
"id": "string",
"role": "OWNER | ADMIN | MEMBER",
"isActive": "boolean",
"userId": "string",
"orgId": "string",
"org": {
"id": "string",
"name": "string",
"slug": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
}
],
"projectMemberships": [
{
"role": "OWNER | ADMIN | MEMBER",
"projectId": "string",
"project": {
"id": "string",
"name": "string",
"slug": "string",
"orgId": "string"
}
}
]
}
}
Update User Profile
PUT
/api/user
Updates the authenticated user's profile information.
Request Body:
{
"name": "string", // Optional: 3-50 characters
"image": "string | null", // Optional: valid URL or null to remove image
"regenerateApiToken": "boolean" // Optional: set to true to regenerate API token
}
Response:
{
"updatedUser": {
"id": "string",
"email": "string",
"name": "string",
"image": "string | null",
"apiToken": "string | null",
"createdAt": "Date",
"updatedAt": "Date"
}
}
Update User Image
PUT
/api/user/image-upload
Uploads and updates the authenticated user's profile image. Replaces the existing image if one exists.
Request Body: Multipart form data
file: Image file (PNG, JPEG, or WebP format, max 2MB)
Response:
{
"imageUrl": "string"
}
Delete User Account
DELETE
/api/user
Permanently deletes the authenticated user's account. Also deletes any organizations where the user is the sole owner.
Response:
{
"success": true,
"message": "User deleted successfully"
}
Organizations
Create Organization
POST
/api/orgs
Creates a new organization with the authenticated user as the owner. Automatically sets the new organization as the user's active organization.
Request Body:
{
"name": "string" // Required: 3-50 characters
}
Response:
{
"organization": {
"id": "string",
"name": "string",
"slug": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
}
Get Organization Details
GET
/api/orgs/{org}
Retrieves details of a specific organization. Requires membership in the organization.
Route Parameters:
org: Organization ID (required).
Response:
{
"organization": {
"id": "string",
"name": "string",
"createdAt": "Date",
"updatedAt": "Date",
"role": "OWNER | ADMIN | MEMBER",
"isActive": "boolean",
"memberships": [
{
"userId": "string",
"role": "OWNER | ADMIN | MEMBER",
"isActive": "boolean",
"user": {
"id": "string",
"name": "string",
"image": "string | null"
}
}
],
"projects": [
{
"id": "string",
"name": "string",
"slug": "string",
"description": "string | null",
"orgId": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
]
}
}
Update Organization
PUT
/api/orgs/{org}
Updates organization information. Only organization owners can perform this action.
Route Parameters:
org: Organization ID (required).
Request Body:
{
"name": "string" // Optional: 3-50 characters
}
Response:
{
"updatedOrg": {
"id": "string",
"name": "string",
"slug": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
}
Delete Organization
DELETE
/api/orgs/{org}
Permanently deletes an organization. Only organization owners can perform this action.
Route Parameters:
org: Organization ID (required).
Response:
{
"success": true,
"message": "Organization deleted successfully"
}
Organization Memberships
Update Organization Member Role
PUT
/api/orgs/{org}/members/{member}
Updates a member's role in the organization. Only owners and admins can update member roles. Cannot promote users to owner roles or modify existing owners. Users cannot change their own role.
Route Parameters:
org: Organization ID (required).member: Member user ID (required).
Request Body:
{
"role": "ADMIN | MEMBER" // Required: the new role for the member
}
Response:
{
"updatedMembership": {
"userId": "string",
"orgId": "string",
"role": "ADMIN | MEMBER",
"isActive": "boolean",
"user": {
// ... User details
},
"org": {
// ... Organization details
}
}
}
Remove Organization Member
DELETE
/api/orgs/{org}/members/{member}
Removes a member from the organization. Members can remove themselves (leave the organization). Only owners and admins can remove other members. Cannot remove organization owners.
Route Parameters:
org: Organization ID (required).member: Member user ID (required).
Response:
{
"success": true,
"message": "Member removed successfully"
}
Create Organization Invite
POST
/api/orgs/{org}/invite/create
Creates an invitation link for new members to join the organization. Only owners and admins can create invitations. Invitations expire after 12 hours.
Route Parameters:
org: Organization ID (required).
Response:
{
"invitation": {
"id": "string",
"orgId": "string",
"token": "string",
"expiresAt": "Date",
"invitedById": "string",
"org": {
// ... Organization details
},
"invitedBy": {
// ... User details
}
},
"inviteUrl": "string"
}
Accept Organization Invite
POST
/api/orgs/{org}/invite/accept
Accepts an invitation to join an organization. Adds the authenticated user as a member with the member role.
Route Parameters:
org: Organization ID (required).
Request Body:
{
"token": "string" // Required: invitation token
}
Response:
{
"organization": {
// ... Organization details
},
"membership": {
"userId": "string",
"orgId": "string",
"role": "MEMBER",
"isActive": "boolean",
"org": {
// ... Organization details
},
"user": {
// ... User details
}
}
}
Audit Logs
Get Organization Audit Logs
GET
/api/orgs/{org}/audit
Retrieves audit logs for an organization with optional filtering and pagination. Only owners and admins can access audit logs.
Route Parameters:
org: Organization ID (required).
Query Parameters:
page: Page number (default: 1)limit: Items per page, max 100 (default: 20)projectId: Filter by project IDaction: Filter by action string (case-insensitive partial match)userId: Filter by user IDstartDate: Filter logs created after this date (ISO 8601 datetime)endDate: Filter logs created before this date (ISO 8601 datetime)
Response:
{
"auditLogs": [
{
"id": "string",
"action": "string",
"resource": "string",
"description": "string",
"metadata": "object | null",
"userId": "string",
"orgId": "string",
"projectId": "string | null",
"createdAt": "Date",
"user": {
// ... User details
},
"project": {
// ... Project details
}
}
],
"pagination": {
"page": "number",
"limit": "number",
"totalPages": "number",
"totalItems": "number",
"hasNext": "boolean",
"hasPrev": "boolean"
},
"filters": {
"users": [
{
"id": "string",
"name": "string",
"email": "string"
}
],
"projects": [
{
"id": "string",
"name": "string"
}
],
"actions": ["string"]
}
}
Delete Organization Audit Logs
DELETE
/api/orgs/{org}/audit
Deletes audit logs in an organization based on specified filters. Only organization owners can perform this action.
Route Parameters:
org: Organization ID (required).
Request Body:
{
"olderThan": "string", // Optional: ISO 8601 datetime, delete logs older than this date
"projectId": "string", // Optional: filter by project ID
"userId": "string", // Optional: filter by user ID
"action": "string" // Optional: filter by action (case-insensitive partial match)
}
Response:
{
"success": true,
"message": "Deleted 10 audit log(s)"
}
Projects
Get Projects
GET
/api/projects
Retrieves all projects the authenticated user has access to, including their organization, memberships, and secrets.
Response:
{
"projects": [
{
"id": "string",
"name": "string",
"slug": "string",
"description": "string | null",
"orgId": "string",
"createdAt": "Date",
"updatedAt": "Date",
"org": {
// ... Organization details
},
"memberships": [
{
"userId": "string",
"projectId": "string",
"role": "OWNER | ADMIN | MEMBER",
"user": {
// ... User details
}
}
],
"secrets": [
{
"id": "string",
"key": "string",
"description": "string | null",
"projectId": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
]
}
]
}
Create Project
POST
/api/projects
Creates a new project in an organization. Only organization owners and admins can create projects. The authenticated user becomes the project owner.
Request Body:
{
"name": "string", // Required: 3-50 characters
"slug": "string", // Optional: 3-50 characters, lowercase letters, numbers, and hyphens only
"description": "string", // Optional: max 255 characters
"orgId": "string" // Required: organization ID where the project will be created
}
Response:
{
"project": {
"id": "string",
"name": "string",
"slug": "string",
"description": "string | null",
"orgId": "string",
"createdAt": "Date",
"updatedAt": "Date",
"org": {
// ... Organization details
},
"memberships": [
{
"userId": "string",
"projectId": "string",
"role": "OWNER",
"user": {
// ... User details
}
}
],
"_count": {
"secrets": "number"
}
}
}
Update Project
PUT
/api/projects/{project}
Updates project details. Only project owners can perform this action.
Route Parameters:
project: Project ID (required).
Request Body:
{
"name": "string", // Optional: 3-50 characters
"slug": "string", // Optional: 3-50 characters, lowercase letters, numbers, and hyphens only
"description": "string" // Optional: max 255 characters
}
Response:
{
"project": {
"id": "string",
"name": "string",
"slug": "string",
"description": "string | null",
"orgId": "string",
"createdAt": "Date",
"updatedAt": "Date",
"org": {
// ... Organization details
}
}
}
Delete Project
DELETE
/api/projects/{project}
Permanently deletes a project. Only project owners can perform this action. All associated secrets, secret values, memberships, and audit logs are subsequently deleted.
Route Parameters:
project: Project ID (required).
Response:
{
"success": true,
"message": "Project deleted successfully"
}
Project Memberships
Add Project Member
POST
/api/projects/{project}/members
Adds a new member to a project. Only project owners and admins can add members. The user must already be a member of the organization. Users can only be added as admins or members (the owner role is assigned during project creation only).
Route Parameters:
project: Project ID (required).
Request Body:
{
"userId": "string", // Required: user ID to add as member
"role": "ADMIN | MEMBER" // Optional: defaults to MEMBER
}
Response:
{
"projectRole": {
"userId": "string",
"projectId": "string",
"role": "ADMIN | MEMBER",
"user": {
// ... User details
},
"project": {
// ... Project details
}
}
}
Update Project Member Role
PUT
/api/projects/{project}/members/{member}
Updates a member's role in the project. Only owners and admins can update member roles. Cannot promote users to the owner role or modify existing owner roles. Users cannot change their own role.
Route Parameters:
project: Project ID (required).member: Member user ID (required).
Request Body:
{
"role": "ADMIN | MEMBER" // Required: the new role for the member
}
Response:
{
"updatedRole": {
"userId": "string",
"projectId": "string",
"role": "ADMIN | MEMBER",
"user": {
// ... User details
},
"project": {
"id": "string",
"name": "string",
"org": {
// ... Organization details
}
}
}
}
Remove Project Member
DELETE
/api/projects/{project}/members/{member}
Removes a member from a project. Members can remove themselves (leave the project). Only owners and admins can remove other members. Cannot remove project owners.
Route Parameters:
project: Project ID (required).member: Member user ID (required).
Response:
{
"success": true,
"message": "Member removed successfully"
}
Project Secrets
Get Project Secrets
GET
/api/projects/{project}/secrets
Retrieves all secrets for a project with their decrypted values. All project members can view secrets.
Route Parameters:
project: Project ID (required).
Response:
{
"decryptedSecrets": [
{
"id": "string",
"key": "string",
"description": "string | null",
"projectId": "string",
"createdAt": "Date",
"updatedAt": "Date",
"values": [
{
"id": "string",
"secretId": "string",
"environment": "DEVELOPMENT | STAGING | PRODUCTION",
"value": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
],
"project": {
// ... Project details
}
}
]
}
Create Secret
POST
/api/projects/{project}/secrets
Creates a new secret in a project. Only project owners and admins can create secrets. Secret keys must be uppercase with numbers and underscores only.
Route Parameters:
project: Project ID (required).
Request Body:
{
"key": "string", // Required: 1-50 characters, uppercase letters, numbers, and underscores only, cannot start/end with underscore or contain consecutive underscores
"description": "string", // Optional: max 255 characters
"values": [ // Optional: at least 1 value if provided
{
"environment": "DEVELOPMENT | STAGING | PRODUCTION", // Required: environment type
"value": "string" // Required: 1-1000 characters
}
]
}
Response:
{
"id": "string",
"key": "string",
"description": "string | null",
"projectId": "string",
"createdAt": "Date",
"updatedAt": "Date",
"values": [
{
"id": "string",
"secretId": "string",
"environment": "DEVELOPMENT | STAGING | PRODUCTION",
"value": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
],
"project": {
"id": "string",
"name": "string",
"org": {
// ... Organization details
}
}
}
Update Secret
PUT
/api/projects/{project}/secrets/{secret}
Updates a secret's description or environment values. Only project owners and admins can update secrets. Values are upserted (created if not exist, updated if exist).
Route Parameters:
project: Project ID (required).secret: Secret ID (required).
Request Body:
{
"description": "string | null", // Optional: max 255 characters
"values": [ // Optional: at least 1 value if provided
{
"environment": "DEVELOPMENT | STAGING | PRODUCTION", // Required: environment type
"value": "string" // Required: 1-1000 characters
}
]
}
Response:
{
"id": "string",
"key": "string",
"description": "string | null",
"projectId": "string",
"createdAt": "Date",
"updatedAt": "Date",
"values": [
{
"id": "string",
"secretId": "string",
"environment": "DEVELOPMENT | STAGING | PRODUCTION",
"value": "string",
"createdAt": "Date",
"updatedAt": "Date"
}
],
"project": {
"id": "string",
"name": "string",
"org": {
// ... Organization details
}
}
}
Delete Secret
DELETE
/api/projects/{project}/secrets/{secret}
Permanently deletes a secret and all its environment values. Only project owners and admins can delete secrets.
Route Parameters:
project: Project ID (required).secret: Secret ID (required).
Response:
{
"success": true,
"message": "Secret deleted successfully"
}