Resources / API docs
API docs
Use API keys to sync Nomo meetings, action items, and decisions into Obsidian or your own tooling.
Obsidian Sync API
Integrate Nomo meeting notes with Obsidian, custom scripts, or any application. Sync your meetings, action items, and decisions programmatically.
https://nomo.whiletruelab.com/api/obsidianAuthentication
All API requests require an API key. Generate one from Settings → Integrations → Obsidian.
Include your API key in requests using one of these methods:
Authorization Header (Recommended)
Authorization: Bearer sk_obs_YOUR_API_KEYX-API-Key Header
X-API-Key: sk_obs_YOUR_API_KEYSecurity Note: Keep your API key secret. Do not expose it in client-side code or public repositories. If compromised, revoke it immediately from the settings page.
Rate Limiting
The API is rate limited to 100 requests per minute per API key.
Rate limit information is included in response headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests per window (100) |
| X-RateLimit-Remaining | Requests remaining in current window |
| X-RateLimit-Reset | Unix timestamp when window resets |
If you exceed the rate limit, you will receive a 429 Too Many Requests response with a Retry-After header.
Endpoints
/authExample Request
curl -X POST https://nomo.whiletruelab.com/api/obsidian/auth \
-H "Authorization: Bearer sk_obs_YOUR_API_KEY" \
-H "Content-Type: application/json"Example Response
{
"valid": true,
"userId": "8ff206b3-890f-4518-8dbd-9401f9809bf9",
"settings": {
"meetings_folder": "Meetings",
"decisions_folder": "Decisions",
"auto_create_decision_notes": true,
"template_id": "standard",
"include_transcript": true,
"file_naming_pattern": "{date} - {title}",
"link_attendees_as_people": true,
"use_utc_timestamps": false,
"sync_frequency_minutes": 30
}
}/syncParameters
| Name | Type | Required | Description |
|---|---|---|---|
| since | ISO 8601 | Optional | Only return meetings updated after this timestamp |
| limit | number | Optional | Max meetings to return (default: 50, max: 100) |
| offset | number | Optional | Pagination offset (default: 0) |
| status | string | Optional | Filter by minutes status (default: 'completed') |
| project_id | string | Optional | Filter by project name |
Example Request
curl "https://nomo.whiletruelab.com/api/obsidian/sync?limit=10&since=2024-01-01T00:00:00Z" \
-H "Authorization: Bearer sk_obs_YOUR_API_KEY"Example Response
{
"meetings": [
{
"id": "a2e98414-3b50-4be0-8f50-408ef3087a59",
"title": "Weekly Team Standup",
"meetingDate": "2024-01-15T10:00:00Z",
"fileName": "2024-01-15 - Weekly Team Standup.md",
"folder": "Meetings",
"obsidianMarkdown": "---\ndate: 2024-01-15\n...",
"decisions": [
{
"id": "dec_123",
"decision": "Adopt new testing framework",
"fileName": "2024-01-15 - Adopt new testing framework.md",
"folder": "Decisions",
"obsidianMarkdown": "---\ntags: [decision]\n..."
}
],
"updatedAt": "2024-01-15T11:30:00Z"
}
],
"pagination": {
"limit": 10,
"offset": 0,
"total": 42,
"hasMore": true
},
"lastSync": "2024-01-15T11:30:00Z",
"serverTime": "2024-01-16T08:00:00Z"
}/meetings/:idParameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | UUID | Required | The meeting ID (UUID format) |
Example Request
curl "https://nomo.whiletruelab.com/api/obsidian/meetings/a2e98414-3b50-4be0-8f50-408ef3087a59" \
-H "Authorization: Bearer sk_obs_YOUR_API_KEY"Example Response
{
"meeting": {
"id": "a2e98414-3b50-4be0-8f50-408ef3087a59",
"title": "Weekly Team Standup",
"meetingDate": "2024-01-15T10:00:00Z",
"fileName": "2024-01-15 - Weekly Team Standup.md",
"folder": "Meetings",
"obsidianMarkdown": "---\ndate: 2024-01-15\ntime: 10:00 AM\nduration: 45min\nattendees: [Alice, Bob, Charlie]\ntags: [meeting, standup]\nnomo_id: a2e98414-3b50-4be0-8f50-408ef3087a59\n---\n\n# Weekly Team Standup\n\n## Summary\n\nTeam discussed sprint progress...",
"decisions": [],
"updatedAt": "2024-01-15T11:30:00Z"
}
}Error Responses
| Status | Description | Example |
|---|---|---|
| 401 | Invalid or missing API key | {"error": "Invalid or expired API key"} |
| 404 | Meeting not found or access denied | {"error": "Meeting not found"} |
| 429 | Rate limit exceeded | {"error": "Rate limit exceeded", "retryAfter": 45} |
| 500 | Server error | {"error": "An unexpected error occurred"} |