forked from raindropio/extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
apiary.apib
623 lines (496 loc) · 21.1 KB
/
apiary.apib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
FORMAT: 1A
HOST: https://raindrop.io/v1
# Raindrop.io API 1.0
The first version of the Raindrop.io API is an exciting step forward towards making it easier for users to have open access to their data.
Build something great.
# Group OAuth
The Raindrop.io API uses the OAuth 2.0 protocol for simple, but effective authentication and authorization.
The one thing to keep in mind is that all requests to the API must be made over SSL (https:// not http://).
#### Do you need to authenticate?
Some API not require authentication (public collections or public bookmarks). However, other requests require authentication - specifically requests made on behalf of a user. Authenticated requests require an access_token. These tokens are unique to a user and should be stored securely. Access tokens may expire at any time in the future.
## Receiving an *access_token*
In order to receive an *access_token*, you must do the following:
1. Direct the user to our authorization url.
- If the user is not logged in, they will be asked to log in.
- The user will be asked if they would like to grant your application access to her Raindrop.io data.
2. The server will redirect the user in one of two ways that you choose:
- **Server-side flow (reccommended)**: Redirect the user to a URI of your choice. Take the provided **code** parameter and exchange it for an *access_token* by POSTing the code to our access_token url.
- **Implicit flow**: Instead of handling a code, we include the access_token as a fragment (#) in the URL. This method is less secure, but allows applications without any server component to receive an access_token.
## Server-side (Explicit) Flow
Using the server-side flow is quite easy. Simply follow these steps:
### Step One: Direct your user to our authorization URL
`https://raindrop.io/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code`
At this point, we present the user with a login screen and then a confirmation screen where to grant your app access to her Raindrop.io data.
### Step Two: Receive the redirect from Raindrop.io
Once a user authorizes your application, we issue a redirect to your redirect_uri with a code parameter to use in step three.
`http://your-redirect-uri?code=CODE`
> Note that the host and path components of your redirect URI must match exactly (including trailing slashes) your registered redirect_uri.
If your request for approval is denied by the user, then we will redirect the user to your redirect_uri with the following parameters:
- **error**: access_denied
`http://your-redirect-uri?error=access_denied`
> It is your responsibility to fail gracefully in this situation and display a corresponding error message to your user.
### Step Three: Request the access_token
Now you need to exchange the **code** you have received in the previous step for an access token. In order to make this exchange, you simply have to POST this code, along with some app identification parameters, to our *access_token* endpoint. These are the required parameters:
- **client_id**: your client id
- **client_secret**: your client secret
- **grant_type**: **authorization_code** is currently the only supported value
- **redirect_uri**: the redirect_uri you used in the authorization request. Note: this has to be the same value as in the authorization request.
- **code**: the exact code you received during the authorization step.
This is a sample request:
```
curl -F 'client_id=CLIENT_ID' \
-F 'client_secret=CLIENT_SECRET' \
-F 'grant_type=authorization_code' \
-F 'redirect_uri=AUTHORIZATION_REDIRECT_URI' \
-F 'code=CODE' \
https://raindrop.io/oauth/access_token
```
If successful, this call will return a neatly packaged OAuth Token that you can use to make authenticated calls to the API:
```
{
"access_token": "Ny5EStPDZFpk2HnnEPdg6o79MFNciCD5"
}
```
Even though the access token does not specify an expiration time, your app should handle the case that either the user revokes access, or Raindrop.io expires the token after some period of time. In this case, your meta of your responses will contain an “error_type=OAuthAccessTokenError”. In other words: **do not** assume your access_token is valid forever.
## Client-Side (Implicit) Authentication
If you are building an app that does not have a server component (a purely javascript app, for instance), you will notice that it is impossible to complete step three above to receive your access_token without also having to store the secret on the client. You should **never** pass or store your client_id secret onto a client. For these situations there is the Implicit Authentication Flow.
### Step One: Direct your user to our authorization URL
`https://raindrop.io/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token`
At this point, we present the user with a login screen and then a confirmation screen where they grant your app’s access to their Raindrop.io data. Note that unlike the explicit flow the response type here is “token”.
### Step Two: Receive the access_token via the URL fragment
Once the user has authenticated and then authorized your application, Instagram redirects them to your redirect_uri with the access_token in the url fragment. It will look like this:
`http://your-redirect-uri#access_token=ACCESS-TOKEN`
Simply grab the access_token off the URL fragment and you’re good to go. If the user chooses not to authorize your application, you’ll receive the same error response as in the explicit flow
# Group Authentication
There are two ways to authenticate through Raindrop.io API.
### OAuth2 Token (sent in a header)
`curl -H "Authorization: Bearer OAUTH_TOKEN" https://raindrop.io/v1/user`
### OAuth2 Token (sent as a parameter)
`curl https://raindrop.io/v1/user?access_token=OAUTH_TOKEN`
# Group Errors
Every response from API have **result** boolean field. Also some methods have **error** string field.
```
{
"result": false,
"error": "CollaboratorsIncorrectToken"
}
```
# Group Users
## User [/user/{user_id}]
Get authenticated user or a specific user id.
> If you getting specific user id response *email* field will be MD5 hash. For example you can use it for Gravatar URL.
### Retrieve [GET]
+ Parameters
+ user_id (number,optional) ... By default current user.
+ Response 200 (application/json)
{
"user": {
"_id": 32,
"email": "User's email",
"fullName": "User's full name",
"groups": [ /*Array of groups*/
{
"title": "Group name",
"collections": [1,2,3], /*id's of collections which are in this group*/
"hidden": false /*Group collapsed or not*/
}
]
},
"result": true
}
## User actions [/user/config]
Only for the authenticated user.
### Update groups [PUT]
+ Request (application/json)
{
"groups": [
{
"title":"Group name",
"collections": [1,2,3],
"hidden": false
}
]
}
+ Response 200 (application/json)
### Change language [PUT]
+ Request (application/json)
{
"lang": "en_US"
}
+ Response 200 (application/json)
## Tags [/tags]
All tags of authenticated user sorted by frequency of use
### Retrieve [GET]
+ Response 200 (application/json)
{
"items":[
{"_id":"angular","count":8}
],
"result": true
}
## Sites [/sites]
All domains of authenticated user sorted by frequency of use
### Retrieve [GET]
+ Response 200 (application/json)
{
"items":[
{"_id":"dribbble.com","count":70}
],
"result": true
}
## Statistics [/stat]
Count of bookmarks by type of authenticated user.
### Retrieve [GET]
+ Response 200 (application/json)
{
"items":[
{"_id":"link","count":455},
{"_id":"article","count":150},
{"_id":"image","count":95},
{"_id":"video","count":14}
],
"result": true
}
# Group Collections
One collection have such fields:
- **_id** - incremental id
- **title** - name of collection
- **excerpt** - description (optional)
- **count** - count of bookmarks in this collection
- **created** - date of creation
- **lastUpdate** - date of last update
- **public** - public (true) or private (false) collection
- **view** - style of view as "list", "grid", "masonry" (pinterest style), "simple" (very simple list). In your interface you can support only "list" and "grid" styles. But bind "masonry" to "grid" and "simple" to "list" view style.
- **cover** - array with one item. Icon of collection
- **parent.$id** - parent collection id. If not specified will be root collection
## Collections [/collections/{user_id}{?parent}]
### Retrieve collections [GET]
> You can retrieve public collections of specific user without *access_token*
+ Parameters
+ user_id (number, optional) ... By default current user
+ parent (number, optional) ... Parent collection id. By default root collections.
+ Response 200 (application/json)
{
"items":[
{
_id: 9,
title: "Collection title",
user.$id: 32,
excerpt: "Description",
count: 1,
created: Date,
lastUpdate: Date,
public: true,
view: "list", /* Can be "list", "grid", "masonry", "simple" */
cover: ["/img/templates/basketball.png"],
parent.$id: 0
}
],
"result": true
}
## Collection [/collection/{id}]
### Retrieve collection [GET]
> You can retrieve public collection without *access_token*
+ Parameters
+ id (number, required) ... Collection id
+ Response 200 (application/json)
{
"item": {
"_id": 9,
"title": "Collection title",
"user.$id": 32,
"excerpt": "Description",
"count": 1,
"created": Date,
"lastUpdate": Date,
"public": true,
"view": "list",
"cover": ["/img/templates/basketball.png"],
"parent.$id": 0
},
"result": true
}
### Create collection [POST]
+ Parameters
+ id (optional) ... Not required
+ Request (application/json)
{
"title",
"excerpt",
"public",
"view",
"parentId", /*"root" or id of parent collection (optional)*/
"cover_path" /*name of icon. For example "airplane". Entire list of icons in API docs. (optional) */
}
+ Response 200 (application/json)
{
"item": {
"_id": 9,
"title": "Collection title",
"user.$id": 32,
"excerpt": "Description",
"count": 1,
"created": Date,
"lastUpdate": Date,
"public": true,
"view": "grid"/"list",
"cover": ["/img/templates/basketball.png"],
"parent.$id": 0
},
"result": true
}
### Update collection [PUT]
+ Parameters
+ id (number, required) ... Collection id
+ Request (application/json)
{
"title",
"excerpt",
"public",
"view",
"parentId", /*"root" or id of parent collection (optional)*/
"cover_path" /*name of icon. For example "airplane". Entire list of icons in API docs. (optional) */
}
+ Response 200 (application/json)
{
"item": {
"_id": 9,
"title": "Collection title",
"user.$id": 32,
"excerpt": "Description",
"count": 1,
"created": Date,
"lastUpdate": Date,
"public": true,
"view": "grid"/"list",
"cover": ["/img/templates/basketball.png"],
"parent.$id": 0
},
"result": true
}
### Delete collection [DELETE]
+ Parameters
+ id (number, required) ... Collection id
+ Response 200 (application/json)
{
"result": true
}
## Childrens [/collections/childrens]
Getting all collections with positive parent_id field. Available only for users with PRO account.
### Retrieve all childrens [GET]
+ Response 200 (application/json)
{
"items": [],
"result": true
}
## Collaborators [/collection/{collection_id}/collaborators]
Working with shared collections and their members/collaborators.
### Retrieve collaborators of collection [GET]
+ Parameters
+ id (number, required) ... Collection id
+ Response 200 (application/json)
{
"items": [
{
_id: 32,
email: "[email protected]",
fullName: "User Name",
me: true,
role: "owner"
},
{
_id: 47840,
email: "[email protected]",
fullName: "User Name",
role: "member"
},
{
_id: 47840,
email: "[email protected]",
fullName: "User Name",
role: "viewer"
}
]
"result": true
}
### Invite collaborator by email [POST]
+ Parameters
+ id (number, required) ... Collection id
+ Request (application/json)
{
"accesslevel": "member", /* "member" or "viewer" */
"emails": "[email protected], [email protected]" /* emails separated by comma */
}
+ Response 200 (application/json)
{
"result": true,
"emails": ["[email protected]", "[email protected]"]
}
### Update collaborator access level [PUT]
+ Parameters
+ id (number, required) ... Collection id
+ Request (application/json)
{
"accesslevel": "member", /* "member" or "viewer" */
"userId": 32
}
+ Response 200 (application/json)
{
"result": true
}
### Remove all collaborators [DELETE]
+ Parameters
+ id (number, required) ... Collection id
+ Response 200 (application/json)
{
"result": true
}
## Icons [/collections/icons]
Collection icon templates. Full path to icon will be "https://raindrop.io/{path}/{icon_name}.png". But when you create or update collection you need specify only *{icon_name}*, not full path.
### Retrieve [GET]
+ Response 200 (application/json)
{
"result": true,
"items": {
"airplane",
"aquarium",
"attantion"
},
"path":"/img/templates/"
}
# Group Bookmarks
One bookmark have such fields:
- **collection.$id** - where bookmark is placed. Can be any collection id or reserved id from this list: *-1* is Inbox, *-99* is Trash.
- **cover** - cover image URL *(optional)*
- **coverId** - cover index from media array *(optional)*
- **domain** - link domain
- **excerpt** - small description *(optional)*
- **lastUpdate** - date of creation or last update
- **link** - bookmark URL
- **media** - array of releated images *(optional)*
- **next** - next in the list bookmark id
- **prev** - previous bookmark id
- **tags** - array of tags *(optional)*
- **title** - title
- **type** - type of bookmark. Can be "link" (default), "article", "image" or "video"
- **removed** - boolean
- **html** - content of page
## Bookmarks [/bookmarks/{collection_id}{?search}{?page}{?perpage}{?sort}]
### Retrive and/or search bookmarks [GET]
> You can retrieve bookmarks from public collection without *access_token*
+ Parameters
+ collection_id (number, required) ... Collection id. Reserved id's: 0 - all bookmarks; -1 - inbox; -99 - trash;
+ search (array, optional) ... For example: [{"key":"tag","val":"angular"}, {"key":"type","val":"article"}]. Available *keys*: word, type, tag, domain. Field *val* is query for type of key.
+ perpage (number, optional) ... How many bookmarks per page. Max 40.
+ page (number, optional) ... 0,1,2,3,4...
+ sort (string, optional) ... Sorting: "lastUpdate" (by date) or "title" (alphabetical)
+ Response 200 (application/json)
{
"result": true,
"author": true, /* if current user is owner */
"items": [
_id: 2,
collection.$id: 210296,
cover: "http://img.com/img.jpg",
coverId: null,
domain: "google.com",
excerpt: "Description",
lastUpdate: Date,
link: "http://google.com/about.html",
media: [{type: "image", link: "http://img.com/img.jpg"}],
next: 3,
prev: 1,
removed: false,
tags: ["angular","js"],
title: "Title",
type: "article",
user.$id: 32
]
}
## Bookmark [/bookmark/{id}]
### Retrieve bookmark [GET]
> You can retrieve bookmark from public collection without *access_token*
+ Parameters
+ id (number, required) ... Bookmark id
+ Response 200 (application/json)
{
"result": true,
"author": true, /* if current user is owner */
"item": [
_id: 2,
collection.$id: 210296,
cover: "http://img.com/img.jpg",
coverId: null,
domain: "google.com",
excerpt: "Description",
lastUpdate: Date,
link: "http://google.com/about.html",
media: [{type: "image", link: "http://img.com/img.jpg"}],
html: "<b>Html content</b>",
next: 3,
prev: 1,
removed: false,
tags: ["angular","js"],
title: "Title",
type: "article",
user.$id: 32
]
}
### Create bookmark [POST]
+ Parameters
+ id (number, optional) ... Not required
+ Request (application/json)
{
collection.$id: 210296, /* collection id (optional) */
cover: "URL", /* cover image (optional) */
coverId: null, /* cover index from media array (optional) */
excerpt: "Description", /* (optional) */
media: [{type: "image", link: "http://img.com/img.jpg"}], /* array of images (optional) */
tags: ["angular","js"], /* (optional) */
title: "Title",
type: "article" /* article/image/video/link (optional) */
}
+ Response 200 (application/json)
### Update bookmark [PUT]
+ Parameters
+ id (number, required) ... Bookmark id
+ Request (application/json)
{
collection.$id: 210296, /* collection id (optional) */
cover: "URL", /* cover image (optional) */
coverId: null, /* cover index from media array (optional) */
excerpt: "Description", /* (optional) */
media: [{type: "image", link: "http://img.com/img.jpg"}], /* array of images (optional) */
tags: ["angular","js"], /* (optional) */
title: "Title",
type: "article" /* article/image/video/link (optional) */
}
+ Response 200 (application/json)
### Delete bookmark [DELETE]
> When you delete bookmark from any collection it will be placed to user **Trash** collection. But if you try remove bookmark from Trash collection it will be removed permanently.
+ Parameters
+ id (number, required) ... Bookmark id
+ Response 200 (application/json)
{
"result": true
}
## Export [/bookmarks/export]
Export all bookmarks in Netscape HTML format.
### Export [GET]
+ Response 200 (text/html)
## Parser [/parse{?url}]
Available only with *access_token*. You can use it for parse some URL and extract useful information from link. For example article body or video from Youtube.
### Parse specific URL [GET]
+ Parameters
+ url (string, required) ... URL
+ Response 200 (application/json)
{
"result":true,
"item":{
"title":"Raindrop.io — Все ваши статьи, фото, видео, ссылки из интернета и приложений в одном месте.",
"excerpt":"Все ваши статьи, фото, видео, ссылки из интернета и приложений в одном месте.",
"media":[{"type":"image","link":"http://raindrop.io/img/logotype-big.png"}],
"html":"",
"type":"link"
}
}