# Logseq API Notes
This document covers quirks, limitations, and best practices when working with the Logseq HTTP API.
## Enabling the API
1. Open Logseq Settings
2. Go to **Features**
3. Enable **HTTP APIs server**
4. Optionally set an authorization token for security
Default URL: `http://localhost:12315`
## API Basics
All API calls are POST requests to `/api` with a JSON body:
```json
{
"method": "logseq.Editor.getPage",
"args": ["Page Name"]
}
```
## Known Quirks
### Page Names are Case-Insensitive
Logseq treats page names as case-insensitive. `"My Page"` and `"my page"` refer to the same page.
### Block UUIDs vs IDs
- **UUID**: String identifier (e.g., `"64a1b2c3-..."`) - stable across sessions
- **ID**: Numeric identifier - may change, don't rely on it
Always use UUIDs when referencing blocks.
### Journal Pages
Journal pages have special naming conventions:
- Format depends on user's configured date format
- Default: `"Dec 4th, 2024"`
- The `journalDay` property is a number like `20241204`
### Empty Blocks
- Blocks with empty content (`""`) are valid
- Some operations may skip empty blocks in results
### Block Content Format
Block content is stored as Markdown with Logseq extensions:
- `[[Page Name]]` - Page references
- `((block-uuid))` - Block references
- `#tag` - Tags
- `TODO`/`DONE` - Task markers (must be at start of block)
### Properties
Block and page properties are stored as key-value pairs:
```
property-name:: value
```
In the API, properties are returned as a `Record<string, unknown>`.
## Rate Limiting
The local API doesn't have rate limiting, but rapid calls can cause:
- UI lag in Logseq
- Potential data consistency issues
Recommendation: Add small delays between bulk operations.
## Datalog Queries
Logseq uses Datascript (a Datalog implementation). Common patterns:
### Find all pages
```clojure
[:find (pull ?p [*])
:where [?p :block/name]]
```
### Find TODOs
```clojure
[:find (pull ?b [*])
:where [?b :block/marker "TODO"]]
```
### Find blocks with specific property
```clojure
[:find (pull ?b [*])
:where [?b :block/properties ?props]
[(get ?props :status) ?status]
[(= ?status "in-progress")]]
```
### Search in content
```clojure
[:find (pull ?b [*])
:where [?b :block/content ?c]
[(clojure.string/includes? ?c "search term")]]
```
## Error Handling
### Common Errors
| Error | Cause | Solution |
|-------|-------|----------|
| Connection refused | Logseq not running or API disabled | Start Logseq, enable API |
| 401 Unauthorized | Missing/invalid token | Check `LOGSEQ_API_TOKEN` |
| Page not found | Page doesn't exist | Check page name spelling |
| Block not found | Invalid UUID | Verify UUID exists |
### Network Errors
The API server only accepts local connections by default. Remote access requires additional configuration.
## Best Practices
1. **Use LogseqOperations** - It handles errors and provides a cleaner API
2. **Check for null** - Many methods return `null` for missing resources
3. **Batch operations carefully** - Too many rapid calls can cause issues
4. **Use search over getAllPages** - More efficient for large graphs
5. **Handle connection errors** - Logseq may not always be running
## Resources
- [Logseq Plugin API Docs](https://plugins-doc.logseq.com/)
- [Logseq Advanced Queries](https://docs.logseq.com/#/page/advanced%20queries)
- [Datascript Documentation](https://github.com/tonsky/datascript)