-
Notifications
You must be signed in to change notification settings - Fork 15
/
apiary.apib
1134 lines (854 loc) · 51.8 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
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
FORMAT: 1A
HOST: https://api.zonky.cz
# Zonky REST API
The Zonky REST API provides programmatic access to Zonky data in JSON format.
We know that API exposed on _api.zonky.cz_ endpoint is public, but please be aware that the part of the API
documented here is a subset of our API we ourselves consider _public_. We expect someone else may use this API and therefore we
try to keep it backward compatible or at least let you know about upcoming changes in advance.
We may not guarantee anything since the API is primarily used by Zonky itself, but you have our promise we will do our best to not break your work.
# Rules of thumb
## Let us know
Please let us know you're building something on top of our API. Just drop an e-mail to [[email protected]](mailto:[email protected]). Why?
We can promote your application to thousands of customers, let you know in advance about upcoming changes or just to know about you.
## Use User-Agent
Every HTTP client should send the User-Agent header according to [HTTP/1.1 semantics and content](https://tools.ietf.org/html/rfc7231#section-5.5.3).
The header should contain application, version and contact information (URL).
* the User-Agent pattern: ```${application}/${version} (${url})```
* the User-Agent example: ```Foo/1.0 (https://github.com/john.doe/foo)```
The User-Agent header helps us in many areas. We may use this header to analyze API changes impact and so on.
## Secure access
Beware, the dark side is listening. Use secure transport protocol (HTTPS) when accessing Zonky.
## User credentials
It's prohibited to ask for credentials (username, password) of other users. It's a security issue and a violation of the
[Zonky terms & conditions](https://zonky.cz/downloads/Zonky_Pravidla_portalu.pdf).
## API Quota, limits, rate limiting, QoS
And other ugly words may follow. Please take into account that even our system has limits. Do to this API as you would have others to do to your own API.
Currently, there is an API Throttle functionality that forbids users to make huge amount of requests per time interval. The algorithm used is [Leaky Bucket](https://en.wikipedia.org/wiki/Leaky_bucket) that refreshes one token every second with a capacity of 500 tokens.
It means that if your robot makes one request per seconds on average, you're fine. You can choose whether it is making one request every second, 500 requests every 500 seconds on something in between. These numbers can be changed anytime so make your client aware of the throttled HTTP response.
In case of client hitting the limit, the API responds with HTTP status code 429 - Too Many Requests.
If you're trying to accomplish any use case and the API Throttling functionality is preventing you from success, please contact us and we'll try to figure something out.
## Bugs and improvements
If you find any bug in our API please use [[email protected]](mailto:[email protected]). Feel free to ask questions or propose improvements regarding the API via [Zonky API GitHub project](https://github.com/zonkyio/zonky-api) or [[email protected]](mailto:[email protected]).
# API Versions and changes
## 0.19.0
* First version available for public audience.
## 0.25.0
* Investing endpoints reference.
## 0.29.0
* Unified default ordering of loans on marketplace for authenticated and anonymous users.
## 0.46.0
* Updated documentation of the loan response.
## 0.54.0
* Added Secondary marketplace resources.
## 0.58.0
* Partial response - possible to filter fields in json responses
## 0.76.0
* Allowing to filter `/users/me/wallet/transactions` resource by a loan ID
## 0.87.0
* Added resource related to insurance
## 0.91.0
* Allowing to filter `/loans/marketplace` resource to show only insured/uninsured loans
## 0.124.0
* Changes to investment endpoints and new fields related to reservations
## 0.129.0
* New fields in marketplace endpoints (preparation for replacing ratings with interest rates)
## 0.4530.0
* Endpoints for making investments and getting last investment removed.
## 0.4531.0
* Endpoints for reservations were removed
You can also subscribe to new releases and be informed about any future change in our api
# OAuth 2 authentication
Zonky users are identified using [OAuth 2.0](http://oauth.net/2/) protocol. At the moment we support following OAuth 2 grant type:
* [Authorization Code Grant Flow ](https://tools.ietf.org/html/rfc6749#page-24) where client app obtains authorization code which is later
exchanged for access token.
In case you're going to create new application that is going to be used by other users, the Authorization Code Grant Flow should be used
because that is the way how you can obtain a grant to user's account without knowing their credentials.
In case you just want to play with the API you can use shared client described below.
In case your app does not have its web service (e.g. a simple mobile app) there is no URL we could redirect the user to we can show user a web page displaying authorization code.
**Acting** on **behalf** of other **users** by supplying their **credentials** is strictly **prohibited**. Applications violating this rule will be banned with no mercy.
## Access token and refresh token
To keep things as secure as possible you have to pay attention to the right usage of OAuth authentication protocol. The right way is to obtain
an access token and a refresh token with user's credentials *on the first authentication request*. Retrieved access token has limited validity (advertised in the
response). After its expiration you should retrieve a new one with a refresh token which has longer validity.
## Authorization Code Grant Flow
### Client onboarding
Client application must obtain client credentials before it can use authorization code flow. To start onboarding process please send us email to [email protected]
with following details
- application name
- application description
- requested scopes (list of scopes this app will need to operate)
- redirect url ( target url where is user redirected after granting authorization code or in case of error) Url is verified for match except for params
Zonky will evaluate your request and if everything is fine we will provide unique clientId and clientSecret for you. **ClientSecret is confidential** and should not
be shared anywhere. Client id and client secret should be used in communication only between secured servers.
### Private access with shared client
If you are running *self hosted* scripts or applications you can use universal access credentials. These credentials are *strictly forbidden* for publicly available robots.
Authorization code will be displayed on web page and must be manually provided to user application/script.
If you are able to provide redirect url (even running on localhost address) it would be easier for you to register your own client as zonky will send authorization code
directly to your application.
Credentials:
clientId: _mujrobot_
clientSecret: _mujrobot_
scopes:
* SCOPE_APP_BASIC_INFO
* SCOPE_INVESTMENT_READ
* SCOPE_INVESTMENT_WRITE
* SCOPE_NOTIFICATIONS_READ
* SCOPE_NOTIFICATIONS_WRITE
accessToken validity: 1 day
redirectUrl: https://app.zonky.cz/api/oauth/code
#### Obtaining authorization code with shared client
1. To obtain authorization code for your application you must open following url: https://app.zonky.cz/api/oauth/authorize?client_id=mujrobot&redirect_uri=https://app.zonky.cz/api/oauth/code&response_type=code&scope=SCOPE_APP_BASIC_INFO+SCOPE_INVESTMENT_READ+SCOPE_INVESTMENT_WRITE&state=opaque in your browser
2. Login to the Zonky and approve access of client MujRobot to your Zonky account
3. Web page with authorization code should appear in your browser
4. You have to provide this code to your application and continue with obtaining an access token. You must hurry as the authorization code is valid only for a limited time (currently 10 minutes)
### Authorization flow
When client needs to connect to protected resource and hasn't valid access token it should redirect user to `oauth/authorize` endpoint( find details at endpoint description).
If user is logged in and client app is not approved zonky will display consent page with some basic info about client app. If client application is already approved
consent page is not displayed again and flow continues directly. After successful approval user is forwarded to redirect url with authorization code.
Client app can use authorization code to retrieve access token by calling `oauth/token` endpoint. In some cases second factor authentication using SMS code can be required.
Authorization code can be used only once and expires after 5 min.
After successful authorization client app can use access token and refresh token for calling secured api. When refresh token expires client app must initiate
new authorization code flow to obtain access and refresh token.
User can revoke application approval anytime and it will lead to immediate revocation of all tokens.
### Scopes
| Scope name | Description |
| :------------- |:------------- |
| <a name="SCOPE_APP_BASIC_INFO">SCOPE_APP_BASIC_INFO</a> | Allow to show only basic info about the user's account (/users/me/basic) |
| <a name="SCOPE_INVESTMENT_READ">SCOPE_INVESTMENT_READ</a>| Allow to show info about investments, allow to display investments export |
| <a name="SCOPE_INVESTMENT_WRITE">SCOPE_INVESTMENT_WRITE</a>| Allow to invest, allow to sell and buy investments on the secondary marketplace |
| <a name="SCOPE_NOTIFICATIONS_READ">SCOPE_NOTIFICATIONS_READ</a>| Allow to view notifications and to show info about them, allow to view notifications configuration |
| <a name="SCOPE_NOTIFICATIONS_WRITE">SCOPE_NOTIFICATIONS_WRITE</a>| Allow notifications settings |
# Pagination, sorting and filtering
All listing resources in this API stick to the same conventions of how to paginate, sort and filter data.
## Pagination
You can query for a subset of data provided by a resource using ```X-Page``` and ```X-Size``` headers. Numbering starts with ```0``` and reasonable defaults are set for cases when
no headers are present in the request.
Total number of records is indicated in the response with ```X-Total``` header.
For example if you query a resource with a total of 40 records with headers ```X-Page: 0``` and ```X-Size: 20``` the API will return records ```0-19```
and ```X-Total: 40``` header value.
## Sorting
You can sort output data by setting ```X-Order``` header in the request. As a value use list of field names separated by a comma ```,```.
Putting ```-``` before the field name indicates descending order.
For example:
+ ```X-Order: -interestRate,termInMonths``` retrieves list of loans with highest interest rate and shortest term on top
## Filtering
Resource records can be filtered by providing query parameters matching the following pattern: ```${fieldName}__${operationSuffix}=${filterValue}```.
| Operation suffix | Description | Possible data types | Examples |
| :------------- | :------------- | :---- | :----- |
| contains | Retrieves object with property containing provided value (case-sensitive) | string | ```?name__contains=foo``` |
| icontains | Retrieves object with property containing provided value (case-insensitive) | string | ```?name__icontains=foo``` |
| startswith | Retrieves object with property starting with provided value (case-sensitive) | string | ```?name__startswith=foo``` |
| istartswith | Retrieves object with property starting with provided value (case-insensitive) | string | ```?name__istartswith=foo``` |
| endswith | Retrieves object with property ending with provided value (case-sensitive) | string | ```?name__endswith=foo``` |
| iendswith | Retrieves object with property ending with provided value (case-insensitive) | string | ```?name__iendswith=foo``` |
| in | Retrieves object if property is contained in provided list of values (case-sensitive) | enum | ```?rating__in=["AAA","AA"]``` |
| eq | Retrieves object if property equals to provided value (case-sensitive) | enum, string, number, date | ```?rating__eq=A``` |
| noteq | Retrieves object if property not equals to provided value (case-sensitive) | enum, string, number, date | ```?rating__noteq=A``` |
| gt | Retrieves object if property is greater than provided value | number, date | ```termInMonths__gt=24``` |
| gte | Retrieves object if property is greater or equal to provided value | number, date | ```termInMonths__gte=24``` |
| gteornull | Retrieves object if property is greater or equal to provided value or is null | number, date | ```termInMonths__gteornull=24``` |
| lt | Retrieves object if property is less than provided value | number, date | ```termInMonths__lt=24``` |
| lte | Retrieves object if property is less or equal to provided value | number, date | ```termInMonths__lte=24``` |
| lteornull | Retrieves object if property is less or equal to provided value or is null | number, date | ```termInMonths__lteornull=24``` |
| containsall | Retrieves object if property is collection of simple values (string, number) and contains all values in the provided list | collection | ```listField__containsall=["value1","value2"]``` |
| containsany | Retrieves object if property is collection of simple values (string, number) and contains any value from the provided list | collection | ```listField__containsany=["value1","value2"]``` |
## Data types
When filtering with ```gt```, ```gte```, ```lt```, ```lte``` it is possible to use ISO-8601 [date](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_DATE) or [datetime](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_OFFSET_DATE_TIME) data type in format,
for example ```datePublished__gt=2016-08-20T23:59:59.000+02:00``` or ```datePublished__lt=2016-08-20```. When no time zone offset is present in incoming data, API will use default platform time zone
(```Europe/Prague```) for parsing.
## Sorting and filtering restrictions
Not all fields are available for sorting and filtering. In such cases you will be informed that your action is not allowed with a response ```400 Bad Request```
and details in the response body:
```json
{
"error" : "invalid_filter",
"error_description" : "Filter or ordering property not allowed: amount",
"uuid" : "25f1f568-e8d1-4066-97a3-110e679dd6ee",
"property" : "amount",
"operation" : "X-Order"
}
```
## Partial response
To relieve network throughput, fields in json responses can be filtered out by providing query parameter ```fields``` with comma separated list of fields that you are interested in. Nested objects can be filtered
with `.` notation. There is simple filter to include all fields of nested object with `.*`
Examples:
- ```GET https://api.zonky.cz/loans/marketplace?fields=id,url```
- ```GET https://api.zonky.cz/loans/marketplace?fields=id,url,borrowerRelatedInfo.*```
- ```GET https://api.zonky.cz/loans/marketplace?fields=id,photos.url```
- ```GET https://api.zonky.cz/loans/marketplace?fields=id,photos.*```
Request:
```GET https://api.zonky.cz/loans/marketplace?fields=id,url```
Response:
```json
[
{
"id": 123,
"url": "https://app.zonky.cz/loan/123"
},
{
"id": 456,
"url": "https://app.zonky.cz/loan/456"
}
]
```
# Group OAuth
## Authorize [/oauth/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scopes}&state={state}]
Endpoint specification is based on oauth specification
### Get authorization code [GET]
+ Parameters
+ client_id (string) - ID of client app
+ redirect_uri (string) - Callback url where user is forwarded with authorization code. Redirect uri host and path must match with redirect uri provided during onboarding process.
+ scopes (string) - **Space** separated list of scopes.
+ state (string) - Nonce value that will be returned when user is redirected back. Client should check, that state matches. This value is opaque for authorization server and client can send any value as long as it is unique for every request
+ Response 302
+ Headers
Location: Redirect url with param `code` and `state`. In case of error `error` and optionally `error_code` is returned instead
## Token [/oauth/token]
Token authentication endpoint.
+ Model (application/json)
```json
{
"access_token" : "c5f6b996-47aa-4c59-8fc7-8a03fcf5da9d",
"token_type" : "bearer",
"refresh_token" : "d33c18a7-cc94-4e35-9ac3-c67528a602f4",
"expires_in" : 299,
"scope" : "SCOPE_APP_BASIC_INFO"
}
```
### Get access token [POST]
+ Request Get access token with authorization code (application/x-www-form-urlencoded)
+ Headers
Authorization: Basic base64 client credentials
+ Body
scope={scopes}&grant_type=authorization_code&code={authorization_code}&redirect_uri={redirect_uri}
+ Parameters
+ redirect_uri (string) - Same url that was used in oauth/authorize endpoint.
+ scopes (string) - **Space** separated list of scopes.
+ authorization_code (string) - Authorization code
+ Response 200 (application/json)
[Token][]
+ Request Renew the access token with the refresh token (application/x-www-form-urlencoded)
+ Headers
Authorization: Basic base64 client credentials
+ Body
refresh_token={refresh_token}&grant_type=refresh_token&scope={scopes}
+ Parameters
+ refresh_token (string) - Refresh token.
+ scopes (string) - **Space** separated list of scopes.
+ Response 200
[Token][]
# Group User
Basic operations with user.
## Basic Info [/users/me/basic]
Get basic information about logged in user. It can be used to personalize your app or if you use zonky as SSO provider
**Required scopes**
* [SCOPE_APP_BASIC_INFO](#SCOPE_APP_BASIC_INFO)
### GET
+ Request (application/json)
+ Headers
```
Authorization: Bearer 674e7f35-7aba-4cec-858c-f48861e9dc21
```
+ Response 200 (application/json)
+ Body
```json
{
"id" : 123,
"username" : "[email protected]",
"email" : "[email protected]",
"firstName" : "Jan",
"surname" : "Novák",
"nickName" : "testuser"
}
```
# Group Marketplace
## Marketplace [/loans/marketplace]
Overview of loans on the marketplace.
### GET
Get loans on marketplace.
**Required scopes**
* none
Available sorting and filtering fields:
| Field | Sorting | Filtering |
| :------------- |:-------------:|:-----:|
|```datePublished```| YES| YES |
|```interestRate```| YES| YES |
|```covered```| YES| YES |
|```termInMonths```| YES| YES |
|```purpose```| YES| YES |
|```rating```| YES| YES |
|```incomes```| NO | YES |
|```topped```| YES| YES |
|```remainingInvestment```| YES| YES |
|```nonReservedRemainingInvestment```| YES | YES |
|```insuranceActive```| YES | YES |
+ Response 200 (application/json)
+ Attributes (array[Loan])
## Last published loan [/loans/last-published]
**Rate limit**
* This endpoint has special Rate limit policy. When calling this endpoint requests are counted against its own rate limit and doesn't decrease normal rate limit.
This endpoint should be used for periodical polling for marketplace changes with maximum frequency 1 request per second.
**Required scopes**
* none
### GET
Get id of last published loan on marketplace. When id of loan is changed, you know that there is some change on marketplace. If you need information about new loans
you have to call endpoint ```/loans/marketplace``` and use ```datePublished``` filter and sort option
+ Response 200 (application/json)
+ Attributes (LastLoanId)
## Loan [/loans/{id}]
Single loan detail.
+ Parameters
+ id: 1 (integer) - ID of a loan
### GET
Get loan detail.
**Required scopes**
* none
+ Response 200 (application/json)
+ Attributes (Loan)
## Loan investments [/loans/{id}/investments]
Investments of the loan selected by ID.
+ Parameters
+ id: 1 (integer) - ID of a loan
+ Model (application/json)
```json
[
{
"id": 123456,
"amount": 200,
"timeCreated": "2017-01-10T15:10:40.831+01:00",
"investorId": 1234,
"loanId": 66655,
"investorNickname": "Bob",
"status": "ACTIVE"
},
{
"id": 987654,
"amount": 1000,
"timeCreated": "2017-02-12T15:44:26.951+01:00",
"investorId": 5678,
"loanId": 77788,
"investorNickname": "Tom",
"status": "ACTIVE"
}
]
```
### GET
Get investmens for the loan. By default it returns all items. It is for backward compatibility.
**Required scopes**
* [SCOPE_INVESTMENT_READ](#SCOPE_INVESTMENT_READ)
Available sorting fields:
| Field |
| :-------------- |
| ```id``` |
| ```amount``` |
| ```timeCreated``` |
| ```investor.Id``` |
| ```loan.Id``` |
| ```investor.NickName``` |
| ```status``` |
+ Response 200
[Loan investments][]
# Group Secondary marketplace
## Get list of my Investments [/me/investments]
### Get all my investments [GET]
**Required scopes**
* [SCOPE_INVESTMENT_READ](#SCOPE_INVESTMENT_READ)
List of available filter and sort attributes:
| Field | Filter | Sort | Description |
| :----------------------------- | :----: | :--: | :-- |
| ```loan.name``` | | ✓ | _Text_ |
| ```loan.purpose``` | ✓ | | _Enum_ filter any value from loan.purpose |
| ```loan.interestRate``` | | ✓ | _Number_ |
| ```loan.amount``` | ✓ | | _Number_ |
| ```ext.unpaidInstalmentCount``` | ✓ | ✓ | _Number_ |
| ```ext.revenueRate``` | ✓ | | _Number_ |
| ```unpaidPrincipal``` | | ✓ | _Number_ |
| ```loanHealth``` | ✓ | | _Enum_ filter valid options are [NEVER_IN_DUE, HEALTHY_AND_ACTIVE, HISTORICALLY_IN_DUE, CURRENTLY_IN_DUE, ONE_TO_FIFTEEN_DPD, SIXTEEN_TO_THIRTY_DPD, THIRTY_ONE_TO_SIXTY_DPD, SIXTY_ONE_TO_NINETY_DPD, MORE_THAN_NINETY_DPD, PAID_OFF, PAID] |
| ```borrowerPrimaryIncomeType``` | ✓ | | _Enum_ filter any value from borrower.primaryIncomeType |
| ```insuranceStatus``` | ✓ | | _Enum_ filter valid options are [CURRENTLY_INSURED, HISTORICALLY_INSURED, NOT_INSURED] |
| ```borrowerRegion``` | ✓ | | _Enum_ filter any value from borrower.region enum is valid |
| ```sellStatus``` | ✓ | | _Enum_ filter any value from sellStatus enum is valid |
| ```investmentStatus``` | ✓ | | _Enum_ filter valid options are [ACTIVE, PAID, AWAITING_INVESTMENT] |
| ```covidLabel``` | ✓ | | _Enum_ filter valid options are [COVID_19_REQUEST_WAITING, COVID_19_POSTPONEMENT_PROCESSED] |
| ```timeCreated``` | ✓ | ✓ | _Time_ |
| ```timeModified``` | ✓ | ✓ | _Time_ |
| ```id``` | ✓ | ✓ | _Number_ |
+ Response 200 (application/json)
Returns user's investments
+ Attributes (array[Investmentv2],fixed-type)
## My Investments Summary [/me/investments/summary]
### Get summary data for my investments [GET]
**Required scopes**
* [SCOPE_INVESTMENT_READ](#SCOPE_INVESTMENT_READ)
Same filter and sort criteria as for "Get all my investments" endpoint
+ Response 200 (application/json)
+ Attributes (InvestmentSummary)
## My Investment Details [/me/investments/{id}]
+ Parameters
+ id (integer, `628265`)
### Get details of an existing investment [GET]
**Required scopes**
* [SCOPE_INVESTMENT_READ](#SCOPE_INVESTMENT_READ)
+ Response 200 (application/json)
+ Attributes(InvestmentDetail)
+ Response 404
## Investor selling his investments [/users/me/traded-investments]
### Publishing investments [POST]
Offer an investment for sale on the secondary marketplace.
**Required scopes**
* [SCOPE_INVESTMENT_WRITE](#SCOPE_INVESTMENT_WRITE)
+ Request
+ Headers
Content-Type: application/json
Authorization: Bearer 674e7f35-7aba-4cec-858c-f48861e9dc21
+ Attributes ([SMPPublishingRequest][])
+ Response 204
Investment has been successfully published on the secondary marketplace
+ Body
+ Response 400
Investment cannot be published on secondary marketplace
+ Attributes([SMPPublishingError][])
+ Response 409
In case parameters of investment sale send by the client differ from a current parameters Conflict is returned. Current parameters are available in the request body.
+ Body
+ Response 408
Request timeout
+ Body
## Investor managing his existing offers [/users/me/traded-investments/{investmentId}]
+ Parameters
+ investmentId (integer, `123`) - ID of an investment
### Cancelling investment offers [DELETE]
Take investment down from the secondary marketplace
**Required scopes**
* [SCOPE_INVESTMENT_WRITE](#SCOPE_INVESTMENT_WRITE)
+ Response 204
In case investment was successfully taken down from the secondary marketplace.
+ Body
+ Response 410
In case investment could not be taken down due to reason described by `error`.
+ Attributes([SMPCancelOfferError][])
## Purchasing investments on secondary marketplace [/smp/investments]
### Listing investments [GET]
Get the list of investments that are available for purchase on the secondary marketplace.
**Required scopes**
* none
Available sorting and filtering fields:
| Field | Sorting | Filtering | Note |
| :------------- |:-------------:|:-----:|:----- |
|```rating```| YES| YES | |
|```datePublished```| YES| YES | |
|```deadline```| YES| YES | |
|```remainingInstalmentCount```| YES| YES | |
|```remainingPrincipal```| YES| YES | |
|```purpose```| YES| YES | |
|```incomeType```| YES| YES | |
|```delinquent```| NO | NO | When not present or false only healthy loans will be returned |
|```loanHealthInfo``` | NO | YES | |
+ Response 200
Returning list of found investments on secondary marketplace
+ Attributes (array[SMPInvestment])
+ Response 408
Request timeout
+ Body
## Consents [/users/me/consents]
### List of my consents [GET]
Get the list of consents that a user has agreed on.
**Required scopes**
* [SCOPE_INVESTMENT_WRITE](#SCOPE_INVESTMENT_WRITE)
+ Request
+ Headers
Content-Type: application/json
Authorization: Bearer 674e7f35-7aba-4cec-858c-f48861e9dc21
+ Response 200
+ Body
```json
{
"smpConsent": {
"agreedOn": "2020-01-28T21:47:33.339+01:00"
}
}
```
# Group Notifications
## User's notifications [/users/me/notifications]
Get user's notifications. Opened notifications are marked as a read.
### GET
Available types are:
| Type | Description |
| :-------------- |:-------------- |
|```NOOP```|Default type.|
|```LOAN_APPLIED_NO_ACTIVATE```|Long-time application.|
|```APPLICATION_APPROVE```|Application was approved.|
|```APPLICATION_DOCUMENTS```|Documents required to approve an application.|
|```APPLICATION_DOCUMENTS_SECOND```|Documents required to approve an application (second notification).|
|```APPLICATION_AGREEMENT```|Print agreement sent to borrower.|
|```APPLICATION_MARKETPLACE```|Application added to marketplace.|
|```LOAN_PUBLISHED```|Loan was published.|
|```LOAN_SEND_MONEY_BORROWER```|Loan is covered and money is being send. This was replaced by ```LOAN_COVERED```|
|```LOAN_COVERED```|Loan was covered by investors.|
|```LOAN_DELAY_BORROWER```|The borrower fell into delinquency.|
|```LOAN_REPAYMENT_COMPLETED_BORROWER```|Successful repayment of the loan.|
|```LOAN_DEADLINE_INSTALMENT```|The repayment term is approaching.|
|```LOAN_DIFFERENT_LAST_INSTALMENT```|Different amounts of the last installment.|
|```LOAN_PAYMENT_HALF```|Congratulations to repayment of half loan.|
|```LOAN_SUCCESS```|Trading of the investment.|
|```LOAN_CANCEL```|Non-trading of investments.|
|```LOAN_UNSIGNED```|To borrower: approved loan is still unsigned.|
|```WALLET_INCOMING```|Adoption of the money in the wallet.|
|```LOAN_PREPAYMENT```|Early repayment, extraordinary repayment.|
|```LOAN_DELAY_INVESTOR```|Loan overdue.|
|```BORROWER_HEAL```|The borrower has healed.|
|```REQUEST_INVESTOR_WELCOME```|Investor applied.|
|```INSTALMENT_PAID```|The instalment was paid.|
**Required scopes**
* [SCOPE_NOTIFICATIONS_READ](#SCOPE_NOTIFICATIONS_READ)
+ Request
+ Headers
Content-Type: application/json
Authorization: Bearer 674e7f35-7aba-4cec-858c-f48861e9dc21
+ Response 200
+ Body
```json
[
{
"date":"2017-04-20T00:05:55.555+02:00",
"visited":false,
"text":"Opožděná splátka od Novák právě přistála ve vaší peněžence. ",
"link":
{
"type":"BORROWER_HEAL",
"params":
{
"loanId":5555
}
},
"id":222222
},
{
"date":"2017-04-19T11:19:42.320+02:00",
"visited":false,
"text":"Opožděná splátka od zonky1234 právě přistála ve vaší peněžence. ",
"link":
{
"type":"BORROWER_HEAL",
"params":
{
"loanId":66666
}
},
"id":333333
}
]
```
# Data Structures
## Loan (object)
- id: 1 (number, required) - ID of the loan
- url: https://app.zonky.cz/loan/1 (string, optional) - The permalink for the loan
The link refers to the official Zonky website with detail of the loan.
It is intended to be used by 3rd party applications,
which can simply use the obtained link instead of generating a custom one.
The main advantage of this link is guarantee that it will be valid in long term.
- name: Loan refinancing (string, required) - Name of the loan
- story: Dear investors, ... (string) - Short story of the loan. Usually some story about the purpose of a loan that attracts investors
- purpose: `REFINANCING` (enum[string], required) - Purpose of the loan
- Members
- `AUTO_MOTO`
- `EDUCATION`
- `TRAVEL`
- `ELECTRONICS`
- `HEALTH`
- `REFINANCING`
- `HOUSEHOLD`
- `OWN_PROJECT`
- `OTHER`
- photos (array[Photo]) - Photos attached to this loan
- nickName: zonky0 (string, required) - Borrower's nickname
- termInMonths: 42 (number, required) - Loan term (in months)
- interestRate: 0.059900 (number, required) - Interest rate for investors
- revenueRate: 0.049900 (number, required) - revenue rate for investors (loan interest rate - investment fee)
- annuityWithInsurance: 2543.00 (number, required) - loan annuity including insurance premium (if insured)
- rating: AAA (string, required) - Rating of the loan
Rating is a risk category for the loan determined after scoring
- topped (boolean, nullable) - true if loan has been topped, false otherwise
- amount: 200000.00 (number, required) - The amount offered to and accepted by borrower
- countryOfOrigin: `CZ` (string, required) - ISO 3166-1 alpha-2 code of the country the loan is related to
- currency: `CZK` (string, required) - Currency code based on ISO-4217
- remainingInvestment: 152600.00 (number, required) - The remaining amount available for investment, users without a reservation can invest only amount equal to `remainingInvestment - reservedAmount`
- reservedAmount: 0.00 (number, required) - `DEPRECATED`, The amount reserved for investors with a reservation for given loan, when not zero, users without reservations can invest only amount equal to `remainingInvestment - reservedAmount`
- investmentRate: 0.237 (number, required) - Current investment rate
- covered: false (boolean, required) - true if the loan is covered, false otherwise
- datePublished: `2016-04-19T18:25:41.208+02:00` (string, required) - Date of the loan publication on marketplace
- published: true (boolean, required) - true if the loan has been published on the marketplace, false otherwise
- deadline: `2016-04-26T18:23:53.101+02:00` (string, required) - Deadline of the loan
Only loans with deadline after actual date and time are visible in the marketplace
- investmentsCount: 72 (number, required) - The count of investments attached to this loan
- region: 6 (string, required) - The code of the region
- mainIncomeType: EMPLOYMENT (string, required) - The type of the income that is set as primary
- insuranceActive: true (boolean,required) - Insurance is active
- insuranceHistory: InsuranceHistoryItem (array[InsuranceHistoryItem], required) - All insurance intervals
## Photo (object)
- name: 6 (string, required) - Name of the photo
- url: /loans/31959/photos/1987 (string, required) - Relative URL to the photo
## InvestmentSummary (object)
- investmentsCount: `450` (number, required) - Number of investments
- principalRemaining: `67038.00` (number, required) - Sum of remaining principals
- principalPaid: `34251.02` (number, required) - Sum of paid principals
- interestRemaining: `6768.52` (number, required) - Sum of remaining interests
- interestPaid: `13580.28` (number, required) - Sum of paid principals
## InvestmentDetail (object)
- id: `628265` (number, required) - Id of investment
- timeModified: `2020-05-25T12:13:00+01:00` (string, required) - Time when the investment changed last.
- timeCreated: `2020-05-20T12:13:00+01:00` (string, required) - Time when the investment was created.
- principal (object, required)
- total: `200.00` (number, required)
- unpaid: `159.87` (number, required)
- interest (object, required)
- total: `4.98` (number, required)
- unpaid: `4.17` (number, required)
- sellStatus: `SELLABLE_WITHOUT_FEE` (enum[string], required) - Status related to secondary marketplace
- Members
- `SELLABLE_WITH_FEE`
- `SELLABLE_WITHOUT_FEE`
- `NOT_SELLABLE`
- `OFFERED`
- `SOLD`
- isBlockedByAB4: `true` (boolean, required) - Investment is locked by zonky and cannot be sold
- loan (object, required)
- id: `56321` (number, required) - Id of loan
- activeLoanOrdinal: `1` (number, required) - Number of *other* active loans of the same borrower
- publicIdentifier: `123465798` (string,required) - Unique loan identifier
- contractNo: `1007376013` (string, required) - Loan contract number
- userNo: `1237896013` (string,required) - Immutable identifier assigned to borrower
- title: `Restrukturalizace úvěrů` (string, required) - Title or name of loan
- story: `Dlužím, kam se podívám, a chci to splatit.` (string, required) - Loan story
- annuity: `1400` (number, required) - annuity (monthly repayment)
- detailLabels: [`VERIFIED_INCOME`] (array[enum], fixed-type) - additional information about loan status
- Members
- `VERIFIED_BORROWER`
- `VERIFIED_INCOME`
- `CURRENTLY_INSURED`
- `ADDITIONALLY_INSURED`
- `BLACK_FRIDAY`
- `COVID_19_REQUEST_WAITING`
- `COVID_19_POSTPONEMENT_PROCESSED`
- borrower (object, required)
- id: `125646` (number, required) - borrower internal id
- borrowerNo: `123456789` (string,required) - Public unique identifier of the borrower
- primaryIncomeType: `EMPLOYMENT` (enum, required) - borrower primary income type
- Members
- `EMPLOYMENT`
- `SELF_EMPLOYMENT`
- `MATERNITY_LEAVE`
- `ENTREPRENEUR`
- `STUDENT`
- `PENSION`
- `LIBERAL_PROFESSION`
- `UNEMPLOYED`
- `OTHER`
- region: `KARLOVARSKY` (enum, required) - borrower region
- Members
- `HLAVNI_MESTO_PRAHA`
- `STREDOCESKY`
- `JIHOCESKY`
- `PLZENSKY`
- `KARLOVARSKY`
- `USTECKY`
- `LIBERECKY`
- `KRALOVEHRADECKY`
- `PARDUBICKY`
- `VYSOCINA`
- `JIHOMORAVSKY`
- `OLOMOUCKY`
- `MORAVSKOSLEZSKY`
- `ZLINSKY`
- `SLOVENSKO`
- healthStats (object, required)
- paidInstalments: `2` (number, required) - Number of already paid instalments
- longestDaysDue: `64` (number, required) - Maximum number of days after a due date of the oldest unpaid instalment in whole history of loan
- daysSinceLastInDue: `128` (number, required) - Number of days since last due instalment has been repaid
- instalmentsCurrentlyInDue: `1` (number, required) - Number of instalments that are currently in due
- loanHealthInfo (enum, required)
- Members
- `CURRENTLY_IN_DUE` - Last payment is not paid on time
- `HISTORICALLY_IN_DUE` - There is delayed payment in past but currently borrower is paying on time
- `HEALTHY` - There is no delayed payment during whole time
- purpose: `HOUSEHOLD` (enum[string], required)
- Members
- `AUTO_MOTO`
- `EDUCATION`
- `TRAVEL`
- `ELECTRONICS`
- `HEALTH`
- `REFINANCING`
- `HOUSEHOLD`
- `OWN_PROJECT`
- `OTHER`
- countryOfOrigin: `CZ` (enum[string], required) - ISO 3166-1 alpha-2 code of the country the loan is related to
- Members
- `CZ`
- currency: `CZK` (enum[string], required) - Currency code based on ISO-4217
- Members
- `CZK`
- payments (object, required)
- total: `84` (number, required) - Total number of instalments
- unpaid: `56` (number, required) - number of unpaid instalments
- revenueRate: `0.0699` (number, required) - revenue rate for investors (loan interest rate - investment fee)
- interestRate: `0.0749` (number, required) - Loan interest rate (old ratings can be transformed to interest rate)
- hasCollectionHistory: `true` (boolean, required)
- dpd: 1 (number, required) - number of days after a due date of the oldest unpaid instalment
- nextPaymentDate: `2020-05-25` (string, optional) - Due date of the next instalment
- label (enum[string]) - Loan status flags
- Members
- `PENDING`
- `IN_WITHDRAWAL`
- `PAST_DUE_CURRENTLY`
- `PAST_DUE_PREVIOUSLY`
- `TERMINATED`
- smpSellInfo (object, required)
- boughtFor: `198.45` (number, required) - Amount of money you paid for the investment
- remainingPrincipal: `145.78` (number, required) - Remaining amount of money you invested to the investment
- discount: `0.25` (number, required) - Percentage discount from full price selling price of the investment. Value is represented as fraction from 1
- sellPrice: `115.98` (number, required) - Actual selling price. Fee is not included
- fee (object, required)
- value: `1.67` (number, required) - Fee amount when selling the investment
- expiresAt: `2020-12-19T00:00:00.000+01:00` (string, required) - Timestamp when the investment can be sold without fee (ISO-8601 format)
## Investmentv2 (object)
- id: 628265 (number, required) - ID of an investment
- timeModified: `2020-05-25T12:13:00+01:00` (string, required) - Time when the investment changed last.
- timeCreated: `2020-05-20T12:13:00+01:00` (string, required) - Time when the investment was created.
- principal (object, required)
- total: `200.00` (number, required)
- unpaid: `159.87` (number, required)
- interest (object, required)
- total: `4.98` (number, required)
- unpaid: `4.17` (number, required)
- sellStatus: `SELLABLE_WITHOUT_FEE` (enum[string], required) - Status related to secondary marketplace
- Members
- `SELLABLE_WITH_FEE`
- `SELLABLE_WITHOUT_FEE`
- `NOT_SELLABLE`
- `OFFERED`
- `SOLD`
- isBlockedByAB4: `true` (boolean, required) - Investment is locked by zonky and cannot be sold
- loan (object, required)
- id: 568745 (number, required) - ID of a loan related to the investment
- purpose: `HOUSEHOLD` (enum[string], required)
- Members
- `AUTO_MOTO`
- `EDUCATION`