reclaim 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +46 -0
- data/LICENSE.txt +21 -0
- data/README.md +367 -0
- data/bin/reclaim +6 -0
- data/lib/reclaim/cli.rb +297 -0
- data/lib/reclaim/client.rb +337 -0
- data/lib/reclaim/errors.rb +26 -0
- data/lib/reclaim/task.rb +149 -0
- data/lib/reclaim/utils.rb +87 -0
- data/lib/reclaim/version.rb +5 -0
- data/lib/reclaim.rb +57 -0
- metadata +114 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2542e7a0ad06c9e9fef776da44dade129f247eefd519a32705168ef6d678b8bb
|
|
4
|
+
data.tar.gz: b51a8d23c1ce024d30ef4f0390ffdf8603ebb39061b1a6d61b97143300ea1360
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 408a148e25073ed4e6735d6517df1dc2a79c164080489f4d951e43169afa2d5f581d5292b9acbfa624eaeedad5fe7a6517fd5e0dc04a06aba58944303adf7e8b
|
|
7
|
+
data.tar.gz: d52a5412e0830c622d1c5b53a38f7d289e286f51b78230458f88ff1574983bcb62fa5b1d090d3540a3d193799855a9ec5a0072e91e310f9b5d5ebd868ffe2bd4
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2025-11-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Dotenv support for environment variable management
|
|
14
|
+
- Automatic loading of `.env` files for API token configuration
|
|
15
|
+
- Development dependency on `dotenv` gem (~> 2.8)
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Renamed environment variable from `RECLAIM_TOKEN` to `RECLAIM_API_KEY` for clarity
|
|
19
|
+
|
|
20
|
+
## [0.1.0] - 2025-10-29
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- Initial release of Reclaim Ruby client
|
|
24
|
+
- Complete task management API (CRUD operations)
|
|
25
|
+
- Task filtering by status (active, completed, overdue)
|
|
26
|
+
- Time scheme support with fuzzy name matching
|
|
27
|
+
- Task splitting control (prevent splitting or configure chunk sizes)
|
|
28
|
+
- Priority levels (P1-P4)
|
|
29
|
+
- Date management (due dates, defer dates, start times)
|
|
30
|
+
- Comprehensive error handling with custom exception types
|
|
31
|
+
- Command-line interface (`reclaim` executable)
|
|
32
|
+
- CLI commands: list, create, get, update, complete, delete, list-schemes
|
|
33
|
+
- Full test suite (unit tests + integration tests)
|
|
34
|
+
- Zero runtime dependencies (stdlib only)
|
|
35
|
+
- Ruby 3.0+ support
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
- **Client**: HTTP client with authentication and caching
|
|
39
|
+
- **Task Model**: Task representation with status helpers
|
|
40
|
+
- **Utils**: Formatting and parsing utilities
|
|
41
|
+
- **CLI**: Full-featured command-line interface
|
|
42
|
+
- **Errors**: Custom exception hierarchy for better error handling
|
|
43
|
+
|
|
44
|
+
[Unreleased]: https://github.com/benjaminjackson/reclaim-ruby/compare/v0.2.0...HEAD
|
|
45
|
+
[0.2.0]: https://github.com/benjaminjackson/reclaim-ruby/compare/v0.1.0...v0.2.0
|
|
46
|
+
[0.1.0]: https://github.com/benjaminjackson/reclaim-ruby/releases/tag/v0.1.0
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Benjamin Jackson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# Reclaim Ruby Client
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/reclaim)
|
|
4
|
+
[](https://www.ruby-lang.org/)
|
|
5
|
+
|
|
6
|
+
A comprehensive Ruby library for interacting with the [Reclaim.ai](https://reclaim.ai) API. Manage your tasks programmatically with proper error handling, time scheme resolution, caching, and a powerful command-line interface.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Complete Task Management**: Create, read, update, delete, and complete tasks
|
|
11
|
+
- **Time Scheme Support**: Resolve time schemes by name with fuzzy matching
|
|
12
|
+
- **Task Filtering**: Filter tasks by status (active, completed, overdue)
|
|
13
|
+
- **Flexible Scheduling**: Control task splitting, chunk sizes, and defer dates
|
|
14
|
+
- **CLI Tool**: Full-featured command-line interface for task management
|
|
15
|
+
- **Error Handling**: Comprehensive exception handling with custom error types
|
|
16
|
+
- **Zero Dependencies**: Uses only Ruby stdlib (no runtime dependencies)
|
|
17
|
+
- **Well Tested**: Extensive test coverage with unit and integration tests
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Install the gem:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
gem install reclaim
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or add to your Gemfile:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
gem 'reclaim'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
Set your Reclaim.ai API token as an environment variable:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export RECLAIM_API_KEY='your_api_token_here'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Get your API token from your [Reclaim.ai settings](https://app.reclaim.ai/settings/developer).
|
|
42
|
+
|
|
43
|
+
### Using .env Files (Optional)
|
|
44
|
+
|
|
45
|
+
If you have the `dotenv` gem installed, the library will automatically load environment variables from `.env` and `.env.local` files from your current working directory. This is helpful for local development:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# .env
|
|
49
|
+
RECLAIM_API_KEY='your_api_token_here'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**For users of this gem**: If you're using reclaim-ruby as a library in your own project and want .env file support, add dotenv to your project's Gemfile:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
gem 'dotenv', '~> 2.8'
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**For contributors**: dotenv is already included as a development dependency for working on this gem.
|
|
59
|
+
|
|
60
|
+
**File precedence**: `.env.local` takes precedence over `.env` and is typically gitignored for local-only overrides. Environment variables already set in your shell take precedence over .env files.
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Ruby Library
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
require 'reclaim'
|
|
68
|
+
|
|
69
|
+
# Initialize client (uses ENV['RECLAIM_API_KEY'] by default)
|
|
70
|
+
client = Reclaim::Client.new
|
|
71
|
+
|
|
72
|
+
# Or pass token explicitly
|
|
73
|
+
client = Reclaim::Client.new('your_api_token')
|
|
74
|
+
|
|
75
|
+
# Create a task
|
|
76
|
+
task = client.create_task(
|
|
77
|
+
title: 'Important Work',
|
|
78
|
+
due_date: '2025-12-31T17:00:00Z',
|
|
79
|
+
priority: :p1,
|
|
80
|
+
duration: 2.0, # hours
|
|
81
|
+
notes: 'This is important!',
|
|
82
|
+
time_scheme: 'work'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
puts "Created task: #{task.title} (#{task.id})"
|
|
86
|
+
|
|
87
|
+
# List tasks
|
|
88
|
+
active_tasks = client.list_tasks(filter: :active)
|
|
89
|
+
completed_tasks = client.list_tasks(filter: :completed)
|
|
90
|
+
overdue_tasks = client.list_tasks(filter: :overdue)
|
|
91
|
+
all_tasks = client.list_tasks # No filter
|
|
92
|
+
|
|
93
|
+
active_tasks.each do |task|
|
|
94
|
+
puts "#{task.title} - #{task.status} (Priority: #{task.priority})"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Get a specific task
|
|
98
|
+
task = client.get_task('task_id_here')
|
|
99
|
+
|
|
100
|
+
# Update a task
|
|
101
|
+
updated_task = client.update_task(
|
|
102
|
+
task.id,
|
|
103
|
+
title: 'Updated Title',
|
|
104
|
+
priority: :p2,
|
|
105
|
+
duration: 3.0
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Mark task as complete (archives it)
|
|
109
|
+
completed_task = client.complete_task(task.id)
|
|
110
|
+
|
|
111
|
+
# Delete a task
|
|
112
|
+
client.delete_task(task.id)
|
|
113
|
+
|
|
114
|
+
# List available time schemes
|
|
115
|
+
schemes = client.list_time_schemes
|
|
116
|
+
schemes.each do |scheme|
|
|
117
|
+
puts "#{scheme['title']} (#{scheme['id']})"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Get formatted time schemes
|
|
121
|
+
puts client.format_time_schemes
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Task Priorities
|
|
125
|
+
|
|
126
|
+
Tasks support four priority levels:
|
|
127
|
+
|
|
128
|
+
- `:p1` - Highest priority (P1)
|
|
129
|
+
- `:p2` - High priority (P2)
|
|
130
|
+
- `:p3` - Normal priority (P3, default)
|
|
131
|
+
- `:p4` - Low priority (P4)
|
|
132
|
+
|
|
133
|
+
### Task Splitting
|
|
134
|
+
|
|
135
|
+
Control whether tasks can be split into smaller chunks:
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
# Prevent splitting (default)
|
|
139
|
+
task = client.create_task(
|
|
140
|
+
title: 'Deep Work Session',
|
|
141
|
+
duration: 4.0 # Must be scheduled as a single 4-hour block
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Allow splitting with default chunk sizes
|
|
145
|
+
task = client.create_task(
|
|
146
|
+
title: 'Flexible Task',
|
|
147
|
+
duration: 3.0,
|
|
148
|
+
allow_splitting: true # Can be split into 15min-3hr chunks
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Allow splitting with custom minimum chunk size
|
|
152
|
+
task = client.create_task(
|
|
153
|
+
title: 'Research',
|
|
154
|
+
duration: 4.0,
|
|
155
|
+
allow_splitting: true,
|
|
156
|
+
split_chunk_size: 0.5 # Minimum 30-minute chunks
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Full control over chunk sizes
|
|
160
|
+
task = client.create_task(
|
|
161
|
+
title: 'Writing',
|
|
162
|
+
duration: 6.0,
|
|
163
|
+
allow_splitting: true,
|
|
164
|
+
min_chunk_size: 1.0, # Minimum 1 hour
|
|
165
|
+
max_chunk_size: 2.0 # Maximum 2 hours
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Time Schemes
|
|
170
|
+
|
|
171
|
+
Time schemes control when tasks can be scheduled. You can reference them by name:
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
# Use exact name
|
|
175
|
+
task = client.create_task(
|
|
176
|
+
title: 'Work Task',
|
|
177
|
+
time_scheme: 'Work Hours'
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Use alias (fuzzy matching)
|
|
181
|
+
task = client.create_task(
|
|
182
|
+
title: 'Work Task',
|
|
183
|
+
time_scheme: 'work' # Finds "Work Hours"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Supported aliases:
|
|
187
|
+
# - 'work', 'working hours', 'business hours' → finds schemes with 'work'
|
|
188
|
+
# - 'personal', 'off hours', 'private' → finds schemes with 'personal'
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Error Handling
|
|
192
|
+
|
|
193
|
+
The library provides specific exception types:
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
begin
|
|
197
|
+
client = Reclaim::Client.new('invalid_token')
|
|
198
|
+
rescue Reclaim::AuthenticationError => e
|
|
199
|
+
puts "Authentication failed: #{e.message}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
begin
|
|
203
|
+
task = client.get_task('nonexistent_id')
|
|
204
|
+
rescue Reclaim::NotFoundError => e
|
|
205
|
+
puts "Task not found: #{e.message}"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
begin
|
|
209
|
+
task = client.create_task(title: '', time_scheme: 'invalid')
|
|
210
|
+
rescue Reclaim::InvalidRecordError => e
|
|
211
|
+
puts "Validation error: #{e.message}"
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
begin
|
|
215
|
+
# Network or API errors
|
|
216
|
+
tasks = client.list_tasks
|
|
217
|
+
rescue Reclaim::ApiError => e
|
|
218
|
+
puts "API error: #{e.message}"
|
|
219
|
+
puts "Status: #{e.status_code}" if e.status_code
|
|
220
|
+
end
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Command-Line Interface
|
|
224
|
+
|
|
225
|
+
The gem includes a full-featured CLI:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# List active tasks (default)
|
|
229
|
+
reclaim
|
|
230
|
+
reclaim list active
|
|
231
|
+
|
|
232
|
+
# List completed or overdue tasks
|
|
233
|
+
reclaim list completed
|
|
234
|
+
reclaim list overdue
|
|
235
|
+
|
|
236
|
+
# Create a task
|
|
237
|
+
reclaim create --title "Important Meeting Prep" \
|
|
238
|
+
--due 2025-12-31 \
|
|
239
|
+
--priority P1 \
|
|
240
|
+
--duration 2
|
|
241
|
+
|
|
242
|
+
# Create a task that allows splitting
|
|
243
|
+
reclaim create --title "Research Project" \
|
|
244
|
+
--duration 4 \
|
|
245
|
+
--split 0.5 # 30-minute minimum chunks
|
|
246
|
+
|
|
247
|
+
# Get task details
|
|
248
|
+
reclaim get TASK_ID
|
|
249
|
+
|
|
250
|
+
# Update a task
|
|
251
|
+
reclaim update TASK_ID \
|
|
252
|
+
--title "Updated Title" \
|
|
253
|
+
--priority P2
|
|
254
|
+
|
|
255
|
+
# Clear a date field
|
|
256
|
+
reclaim update TASK_ID --due none
|
|
257
|
+
reclaim update TASK_ID --defer clear
|
|
258
|
+
|
|
259
|
+
# Mark task as complete
|
|
260
|
+
reclaim complete TASK_ID
|
|
261
|
+
|
|
262
|
+
# Delete a task
|
|
263
|
+
reclaim delete TASK_ID
|
|
264
|
+
|
|
265
|
+
# List available time schemes
|
|
266
|
+
reclaim list-schemes
|
|
267
|
+
|
|
268
|
+
# Get help
|
|
269
|
+
reclaim help
|
|
270
|
+
reclaim --help
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Development
|
|
274
|
+
|
|
275
|
+
### Setup
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
git clone https://github.com/benjaminjackson/reclaim-ruby.git
|
|
279
|
+
cd reclaim-ruby
|
|
280
|
+
bundle install
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Running Tests
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Run unit tests only (no API calls)
|
|
287
|
+
SKIP_INTEGRATION_TESTS=true bundle exec rake test
|
|
288
|
+
|
|
289
|
+
# Run all tests (requires RECLAIM_API_KEY)
|
|
290
|
+
bundle exec rake test
|
|
291
|
+
|
|
292
|
+
# Run only integration tests
|
|
293
|
+
bundle exec rake test TESTOPTS='-n /Integration/'
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Building the Gem
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
gem build reclaim.gemspec
|
|
300
|
+
gem install ./reclaim-0.1.0.gem
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## API Reference
|
|
304
|
+
|
|
305
|
+
### Reclaim::Client
|
|
306
|
+
|
|
307
|
+
Main client for API interactions.
|
|
308
|
+
|
|
309
|
+
**Methods:**
|
|
310
|
+
|
|
311
|
+
- `initialize(token = nil)` - Create client (uses ENV['RECLAIM_API_KEY'] if token not provided)
|
|
312
|
+
- `create_task(**options)` - Create a new task
|
|
313
|
+
- `list_tasks(filter: nil)` - List all tasks (filter: :active, :completed, :overdue, or nil)
|
|
314
|
+
- `get_task(task_id)` - Get a specific task by ID
|
|
315
|
+
- `update_task(task_id, **options)` - Update an existing task
|
|
316
|
+
- `complete_task(task_id)` - Mark task as complete (ARCHIVED status)
|
|
317
|
+
- `delete_task(task_id)` - Permanently delete a task
|
|
318
|
+
- `list_time_schemes` - Get available time schemes
|
|
319
|
+
- `format_time_schemes` - Get formatted time schemes for display
|
|
320
|
+
|
|
321
|
+
### Reclaim::Task
|
|
322
|
+
|
|
323
|
+
Task model with properties and helper methods.
|
|
324
|
+
|
|
325
|
+
**Properties:**
|
|
326
|
+
|
|
327
|
+
- `id`, `title`, `notes`, `due_date`, `priority`, `duration`
|
|
328
|
+
- `status`, `time_scheme_id`, `always_private`, `event_category`, `event_color`
|
|
329
|
+
- `min_chunk_size`, `max_chunk_size`, `snooze_until`, `start`
|
|
330
|
+
|
|
331
|
+
**Methods:**
|
|
332
|
+
|
|
333
|
+
- `active?` - Check if task is active (not deleted/archived/cancelled)
|
|
334
|
+
- `completed?` - Check if task is completed (COMPLETE or ARCHIVED status)
|
|
335
|
+
- `overdue?` - Check if task is past its due date
|
|
336
|
+
- `due_date_formatted` - Get formatted due date string
|
|
337
|
+
- `priority_symbol` - Get priority as symbol (:p1, :p2, :p3, :p4)
|
|
338
|
+
|
|
339
|
+
### Exception Classes
|
|
340
|
+
|
|
341
|
+
- `Reclaim::Error` - Base exception class
|
|
342
|
+
- `Reclaim::AuthenticationError` - Authentication/token errors
|
|
343
|
+
- `Reclaim::ApiError` - API/network errors (includes status_code and response_body)
|
|
344
|
+
- `Reclaim::NotFoundError` - Resource not found (404)
|
|
345
|
+
- `Reclaim::InvalidRecordError` - Validation errors (422)
|
|
346
|
+
|
|
347
|
+
## Contributing
|
|
348
|
+
|
|
349
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/benjaminjackson/reclaim-ruby.
|
|
350
|
+
|
|
351
|
+
1. Fork it
|
|
352
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
353
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
354
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
355
|
+
5. Create new Pull Request
|
|
356
|
+
|
|
357
|
+
## License
|
|
358
|
+
|
|
359
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
|
|
360
|
+
|
|
361
|
+
## Links
|
|
362
|
+
|
|
363
|
+
- **RubyGems**: https://rubygems.org/gems/reclaim
|
|
364
|
+
- **Source Code**: https://github.com/benjaminjackson/reclaim-ruby
|
|
365
|
+
- **Bug Reports**: https://github.com/benjaminjackson/reclaim-ruby/issues
|
|
366
|
+
- **Reclaim.ai**: https://reclaim.ai
|
|
367
|
+
- **API Documentation**: https://reclaim.ai/api
|