revolut-retail-card-api/README.md

300 lines
7.2 KiB
Markdown
Raw Normal View History

2023-12-24 12:31:46 +01:00
# Revolur Card API
## Base address
https://app.revolut.com/api/revolut-secure/retail
## Headers
```
{
"authority": "app.revolut.com",
"accept": "application/json",
"content-type": "application/jso",
"origin": "chrome-extension://hdlehfdjcalidklijenibmpcdgjfmafn",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
"user-agent": "<chrome user agent>",
"x-browser-application": "BROWSER_EXTENSION",
"x-client-version": "100.0",
"x-device-id": "<random uid>",
"x-device-model": "<same as user agent>"
}
```
## Authentication
### POST /signin
#### Description
Login with phone number and passcode and get a token.
#### Request
```
{
"phone":"<+XX phone>",
"password":"<passcode>",
"channel":"APP"
}
```
#### Response
```
{
"tokenId":"<token uid>"
}
```
### POST /token (issue)
#### Description
Once a token is obtained through the login request, the signin request has to be confirmed on the app. This request is used for polling for that authorization and then getting actual credentials.
#### Request
```
{
"phone":"<+XX phone>",
"password":"<passcode>",
"tokenId":"<token uid>"
}
```
#### Response
##### Case 1 - Authorization Pending
```
{
"message": "One should obtain consent from the user before continuing",
"code": 9035
}
```
##### Case 2 - Authorization Granted
```
{
"tokenExpiryDate": <expiry timestamp>,
"refreshCode": "<refresh code>",
"ownerId": "<owner id>,
"accessToken": "<access token>",
"user": {
"id": "<user id> (should be same as <owner id>)",
"state": "ACTIVE"
}
}
```
### POST /token (refresh)
#### Description
The token has to be periodically refreshed.
#### Request
```
{
"userId":"<user id>"
"refreshCode":"<refresh code>"
}
```
#### Response
```
{
"tokenExpiryDate": <expiry date>,
"refreshCode": "<refresh code>",
"ownerId": "<owner id>",
"accessToken": "<access token>"
}
```
### GET /user/current/picture
#### Description
Get user profile picture.
#### Headers
```
{
"Authorization": <owner id>:<access token>
}
```
#### Response
Profile picture raw bytes.
### GET /user/current
#### Description
Get user details, including email, phone, full address, username, id, code.
#### Headers
```
{
"Authorization": <owner id>:<access token>
}
```
### Response
```
{
"user": {
"id": "<user id>",
"individualId": "<user id>",
"createdDate": <creation date>,
"address": {
"city": "<city>",
"country": "<country code>",
"postcode": "<post code>",
"region": "<region>",
"streetLine1": "<address line 1>",
"streetLine2": "<address line 2>"
},
"birthDate": [
<year>,
<month>,
<day>
],
"firstName": "<first name>",
"lastName": "<last name>",
"phone": "<+XX phone>",
"email": "<email>",
"emailVerified": true,
"state": "ACTIVE",
"referralCode": "<code>",
"code": "<code>",
"kyc": "PASSED",
"underReview": false,
"locale": "en-GB",
"riskAssessed": false,
"username": "<username>",
"identityDetails": {
"accountPurpose": "DAILY_SPENDING",
"taxResidencies": [],
"identificationNumbers": [
{
"country": "<country code>",
"name": "genericTin",
"value": "<?>"
}
]
},
"hasProfilePicture": true,
"appMode": "FULL"
},
"wallet": {
"baseCurrency": "EUR"
}
}
```
### GET /my-card/all
#### Description
Get an array of all the available cards in the account, without secret details. In a personal account, cards can be either virtual or physical. Virtual cards can also be tagged as single use (disposable). It is also known whether a card is for professional use (`PRO`) or for personal use (`RETAIL`).
#### Headers
```
{
"Authorization": <owner id>:<access token>
}
```
#### Response
```
[
{
"id": "<card id>",
"walletId": "<wallet id>",
"label": "<label>",
"state": "ACTIVE",
"virtual": true,
"disposable": false,
"credit": false,
"instalment": false,
"customised": false,
"brand": "MASTERCARD",
"design": "<design enum>",
"designGroup": "VIRTUAL",
"colour": "#<hex color>",
"lastUsedDate": <last used>,
"lastFour": "<last four digits>",
"expiryDate": <expiry date>,
"replaced": false,
"createdDate": <created date>,
"productType": "PRO",
"settings": {
"locationSecurityEnabled": false,
"magstripeDisabled": true,
"atmWithdrawalsDisabled": true,
"ecommerceDisabled": false,
"contactlessDisabled": false,
"initial": false,
"pockets": [
{
"id": "<pocket id>",
"pocketType": "MERCHANT"
},
{
"id": "<pocket id>",
"pocketType": "MERCHANT"
}
]
},
"delivery": {
"status": "NONE"
},
"usage": <?>,
"preexpired": false,
"applePayEligible": true,
"googlePayEligible": true,
"cardClickActivationEligible": false,
"panActivationEligible": false
},
{
"id": "<card id>",
"walletId": "<wallet id>",
"label": "<label>",
"state": "ACTIVE",
"virtual": true,
"disposable": false,
"credit": false,
"instalment": false,
"customised": false,
"brand": "VISA",
"design": "<design enum>",
"designGroup": "VIRTUAL",
"colour": "#<hex color>",
"lastUsedDate": <last used>,
"lastFour": <last four digits>",
"expiryDate": "<expiry date>",
"replaced": false,
"createdDate": <created date>,
"productType": "RETAIL",
"settings": {
"locationSecurityEnabled": false,
"magstripeDisabled": true,
"atmWithdrawalsDisabled": true,
"ecommerceDisabled": false,
"contactlessDisabled": false,
"initial": false,
"pockets": []
},
"delivery": {
"status": "NONE"
},
"usage": <?>,
"preexpired": false,
"applePayEligible": true,
"googlePayEligible": true,
"cardClickActivationEligible": false,
"panActivationEligible": false
}
]
```
### GET /my-card/<card uid>/details
#### Description
Get card secret details: pan, cvv, expiration date. The pan and the cvv are encrypted using AES ECB with the first 32 ascii chars of the token as key.
#### Headers
```
{
"Authorization": <owner id>:<access token>
}
```
#### Response
```
{
"pan":"<base64 of AES encrypted pan>",
"cvv":"<base64 of AES encrypted cvv>",
"expiry":{"month":<month>,"year":<year>}
}
```
## TODO
Support for card termination, issue, freeze, unfreeze, labeling, and creation is quite simple too.