# Betacard API Proposal # Base URL Staging URL: `https://betacard-api.herokuapp.com/api/v1` # Authenticating Requests Please include the `Authorization` in your requests like so: `Authorization: Bearer <TOKEN>` `TOKEN` can be obtained from the response body when [signing in](#Sign-In). # Pagination For endpoints with paginated contents. The pagination information will be included in the response header like so: |HEADER|Description| |--------|---------| |`X-Page`|Current page| |`X-Count`|Current specified count| |`X-Total-Pages`|Total number of pages| |`X-Total-Records`|Total number of records| # Error Every error message conform to this shape ``` { "message": string; "code": string; "errors": []; "timestamp": string; "resource": string; } ``` Example ``` { "message": "Access Code is not found", "code": "access_code_not_found", "errors": [], "timestamp": "2019-10-18T06:04:53Z", "resource": "/api/v1/account/verify_signin" } ``` # Account ### Sign up *Creates an account for new user* |Method|Path| |------|-----------------| |`POST`|`/account/sign_up`| Staging URL: https://betacard-api.herokuapp.com/api/v1/account/sign_up **Request Body** ``` { "phoneNumber": "+60171122345", "firstName": "John", "lastName": "Wick", "email": "johnwick@hightable.global" } ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | New Account successfully created| Body ``` { "id": 5, "phoneNumber": "+60168028426", "createdAt": "2019-10-11T02:41:36Z", "profile": { "id": 5, "email": "deojeff@gmail.com", "isEmailVerified": false, "firstName": "John", "lastName": "Wick", "createdAt": "2019-10-11T02:41:36Z", "updatedAt": "2019-10-11T02:41:36Z" } } ``` | Status Code | Description| |------|-----------------| | **400 Bad Request** | Field validation failed| Body ``` { "message": "Validation Error", "code": "validation_error", "errors": [ { "field": "phoneNumber", "code": "is_defined" }, { "field": "firstName", "code": "is_defined" }, { "field": "lastName", "code": "is_defined" }, { "field": "email", "code": "is_defined" } ], "timestamp": "2019-10-11T06:38:25Z", "resource": "/api/v1/sign_up" } ``` | Status Code | Error | Description | |------|-----------------|----------| | **409 Conflict** | `PhoneNumberInUseException` | Phone Number already in use | Body ``` { "message": "Phone Number Already In Use", "code": "phone_number_in_use", "errors": [], "timestamp": "2019-10-11T06:47:29Z", "resource": "/api/v1/sign_up" } ``` | Status Code | Error | Description | |------|-----------------|----------| | **409 Conflict** | `EmailAlreadyInUseException` | Email already in use | Body ``` { "message": "Email Already In Use", "code": "email_already_in_use", "errors": [], "timestamp": "2019-10-11T08:54:32Z", "resource": "/api/v1/sign_up" } ``` ### Sign In *Creates a sign in request* |Method|Path| |------|------------------| |`POST`| `/account/sign_in`| **Request Body** ``` { "phoneNumber": "+60171122345" } ``` **Response** | Status Code | Description| |------|-----------------| | **204 No Content** | Verification SMS sent| Body ``` { } ``` | Status Code | Error | Description | |------|-----------------|----------| | **404 Not Found** | `PhoneNumberInvalidException` | Phone Number does not exist. | Body ``` { "message": "Phone Number does not exist.", "code": "phone_number_not_valid", "errors": [], "timestamp": "2019-10-15T09:24:01Z", "resource": "/api/v1/signin" } ``` --- ### Verify Sign In Request `POST /account/verify_sign_in` *Verifies sign in request using the code sent via SMS* **Request Body** ``` { "phoneNumber": "+60171122345", "code": "1234" } ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Account successfully verified| Body ``` { "lastUsedAt": "2019-11-12T09:33:59.756Z", "user": { "createdAt": "2019-11-12T03:19:16Z", "updatedAt": "2019-11-12T03:19:16Z", "id": 3, "phoneNumber": "+84912345678", "profile": { "createdAt": "2019-11-12T03:19:16Z", "updatedAt": "2019-11-12T03:19:16Z", "id": 3, "email": "testing@gmail.com", "firstName": "John", "lastName": "Wick" } }, "userAccessCode": { "id": 31, "code": "7028", "recipient": "+84912345678", "expiresAt": "2019-11-12T09:59:37Z", "usedAt": null, "invalidatedAt": null, "user": { "createdAt": "2019-11-12T03:19:16Z", "updatedAt": "2019-11-12T03:19:16Z", "id": 3, "phoneNumber": "+84912345678" } }, "token": "vPXegfWzQ0W4p33FFS0I17GrHhc1Zxxx", "invalidatedAt": null, "id": 2 } ``` | Status Code | Description| |------|-----------------| | **400 Bad Request** | Field validation failed| Body ``` { "message": "Validation Error", "code": "validation_error", "errors": [ { "field": "phoneNumber", "code": "is_defined" }, { "field": "code", "code": "is_defined" } ], "timestamp": "2019-10-11T06:38:25Z", "resource": "/api/v1/verify_signin" } ``` | Status Code | Description| |------|-----------------| | **404 Not Found** | Access code not found | Body ``` { "message": "Access Code is not found", "code": "access_code_not_found", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/verify_signin" } ``` | Status Code | Description| |------|-----------------| | **406 Unprocessable Entity** | Access Code has expired| Body ``` { "message": "Access Code has expired", "code": "access_code_has_expired", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/verify_signin" } ``` | Status Code | Description| |------|-----------------| | **406 Unprocessable Entity** | Access Code has been used| Body ``` { "message": "Access Code has been used", "code": "access_code_has_been_used", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/verify_signin" } ``` ### Sign Out `POST /account/signout` *Sign out user by verifying token* **Request Body** ``` { "token": "$2a$12$z3ZsVNDysDRpF5blkCcAJelJWwi9DyXX94xm5qIgriKVsqpRMdmY.", } ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Account successfully logged out| Body ``` { "id": 1, "token": "$2a$12$QHwkV/aZwrozx0jD2ghGnOfwHtP8QAQJgAhAxumHCQtM.2IEpwry6", "lastUsedAt": "2019-10-16T04:55:19Z", "invalidatedAt": "2019-10-17T10:10:54Z", "user": { "id": 1, "phoneNumber": "+60164104864", "createdAt": "2019-10-15T04:13:31Z" }, "userAccessCode": { "id": 3, "code": "4960", "recipient": "+60164104864", "expiresAt": "2019-10-16T05:13:48Z", "usedAt": "2019-10-16T04:55:19Z", "invalidatedAt": "2019-10-16T05:01:38Z" } } ``` | Status Code | Description| |------|-----------------| | **404 Not Found** | User session cannot be found | Body ``` { "message": "User session cannot be found", "code": "user_session_not_found", "errors": [], "timestamp": "2019-10-17T10:13:02Z", "resource": "/api/v1/account/signout" } ``` | Status Code | Description| |------|-----------------| | **400 Bad Request** | Field validation failed| Body ``` { "message": "Validation Error", "code": "validation_error", "errors": [ { "field": "token", "code": "is_defined" } ], "timestamp": "2019-10-17T10:15:34Z", "resource": "/api/v1/signout" } ``` # Card Theme ### Create Card Theme *Creates a new theme for user* |Method|Path| |------|-----------------| |`POST`|`/card_themes`| **Request Body** ``` { "title": "my first theme", "scheme": { // Contains all the design and layout information }, } ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | New theme successfully created| Body ``` { "title": "my first theme", "id": 1 "scheme": {}, "user": { "createdAt": "2019-11-12T09:07:14Z", "updatedAt": "2019-11-12T09:07:14Z", "id": 1, "phoneNumber": "+601349724954" }, "createdAt": "2019-12-24T07:27:44Z", "updatedAt": "2019-12-24T07:27:44Z", } ``` | Status Code | Description| |------|-----------------| | **400 Bad Request** | Field validation failed| Body ``` { "message": "Validation Error", "code": "validation_error", "errors": [ { "field": "title", "code": "is_defined" }, { "field": "scheme", "code": "is_defined" }, ], "timestamp": "2019-10-11T06:38:25Z", "resource": "/api/v1/card_themes" } ``` ### Get list of Card Themes Retrieves a paginated list of Card Theme sorted by creation time |Method|Path| |------|-----------------| |`GET`|`/card_themes/me`| **Response** ``` [ { "id": 1, "title": "my first theme", "createdAt": "2019-12-24T07:27:44Z", "updatedAt": "2019-12-24T07:27:44Z", "scheme": {}, "user": { "id": 1, "createdAt": "2019-11-12T09:07:14Z", "updatedAt": "2019-11-12T09:07:14Z", "phoneNumber": "+601119724552" } }, { "id": 2, "title": "my second theme", "createdAt": "2019-12-24T07:27:55Z", "updatedAt": "2019-12-24T07:27:55Z", "scheme": {}, "user": { "id": 1, "createdAt": "2019-11-12T09:07:14Z", "updatedAt": "2019-11-12T09:07:14Z", "phoneNumber": "+601119724552" } } ] ``` ### Get One Card Theme By ID Retrieves a single theme by id |Method|Path| |------|-----------------| |`GET`|`/card_themes/:id`| **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Card theme retrieved successfully | Body ``` { "id": 2, "title": "my second theme", "createdAt": "2019-12-24T07:27:55Z", "updatedAt": "2019-12-24T07:27:55Z", "scheme": {}, "user": { "id": 1, "createdAt": "2019-11-12T09:07:14Z", "updatedAt": "2019-11-12T09:07:14Z", "phoneNumber": "+601119724552" } } ``` | Status Code | Description| |------|-----------------| | **404 Not Found** | Card Theme Not Found | Body ``` { "message": "Card Theme Not Found", "code": "card_theme_not_found", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/card_themes/:id" } ``` ### Delete Card Theme *Deletes a Card Theme based on given ID* |Method|Path| |------|-----------------| |`DELETE`|`/card_themes/:id`| **Response** | Status Code | Description| |------|-----------------| | **204 No Content** | Card Theme Successfully Deleted| | Status Code | Description| |------|-----------------| | **404 Not Found** | Card Theme Not Found | Body ``` { "message": "Card Theme Not Found", "code": "card_theme_not_found", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/card_themes/:id } ``` # Card ### Create Card *Creates a new card for user* |Method|Path| |------|-----------------| |`POST`|`/cards`| Insert bearer token for authorization. **Request Body** ``` { "title": "first card", "scheme": { // Contains all the design and layout information }, "fieldData": { // Contains all the labels and values }, "type": "personal", "isFavorite": false } ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | New card successfully created| Body ``` { "id": 1, "type": "personal", "scheme": { //Contains all the design and layout information }, "fieldData": { //Contains all the labels and values }, "details": { "id": 1, "title": "my first card", "isFavorite": false, }, "user": { "id": 1, "phoneNumber": "+60164104864", "createdAt": "2019-10-15T04:13:31Z" }, "updatedAt": "2019-10-17T11:51:46Z", "createdAt": "2019-10-17T11:51:46Z" } ``` | Status Code | Description| |------|-----------------| | **404 Not Found** | User Not Found | Body ``` { "message": "User Not Found", "code": "user_not_found", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/cards } ``` ### Get List of Cards *Get a list of user's card* |Method|Path| |------|-----------------| |`GET`|`/cards/me`| Insert bearer token for authorization. **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Get all user's card succesfully | Body ``` [ { "id": 1, "type": "personal", "scheme": { //Contains all the design and layout information }, "fieldData": { //Contains all the labels and values }, "details": { "id": 1, "title": "my first card", "isFavorite": false, }, "user": { "id": 1, "phoneNumber": "+60164104864", "createdAt": "2019-10-15T04:13:31Z" }, "updatedAt": "2019-10-17T11:51:46Z", "createdAt": "2019-10-17T11:51:46Z" }, { "id": 2, "type": "personal", "scheme": { //Contains all the design and layout information }, "fieldData": { //Contains all the labels and values }, "details": { "id": 2, "title": "my second card", "isFavorite": false, }, "user": { "id": 1, "phoneNumber": "+60164104864", "createdAt": "2019-10-15T04:13:31Z" }, "updatedAt": "2019-10-17T11:51:46Z", "createdAt": "2019-10-17T11:51:46Z" } ] ``` ### Get One Card By ID Retrieves a single theme by id |Method|Path| |------|-----------------| |`GET`|`/cards/:id`| **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Card theme retrieved successfully | Body ``` { "id": 1, "type": "personal", "scheme": { //Contains all the design and layout information }, "fieldData": { //Contains all the labels and values }, "details": { "id": 1, "title": "my first card", "isFavorite": false, }, "user": { "id": 1, "phoneNumber": "+60164104864", "createdAt": "2019-10-15T04:13:31Z" }, "updatedAt": "2019-10-17T11:51:46Z", "createdAt": "2019-10-17T11:51:46Z" } ``` | Status Code | Description| |------|-----------------| | **404 Not Found** | Card Not Found | Body ``` { "message": "Card Not Found", "code": "card_not_found", "errors": [], "timestamp": "2019-12-24T09:00:40Z", "resource": "/api/v1/cards/:id" } ``` ### Update Card Updates a single card by ID |Method|Path| |------|-----------------| |`PUT`|`/cards/:id`| Insert bearer token for authorization. **Request** ``` { "title": "my first card", "scheme": {}, "fieldData": {}, "isFavorite": true } ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Card updated successfully | Body ``` { "id": 1, "type": "personal", "scheme": { //Contains all the design and layout information }, "fieldData": { //Contains all the labels and values }, "details": { "id": 1, "title": "my first card", "isFavorite": false, }, "user": { "id": 1, "phoneNumber": "+60164104864", "createdAt": "2019-10-15T04:13:31Z" }, "updatedAt": "2019-10-17T11:51:55Z", "createdAt": "2019-10-17T11:51:46Z" } ``` | Status Code | Description| |------|-----------------| | **404 Not Found** | Card id not found | Body ``` { "message": "Card id cannot found", "code": "card_id_not_found", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/card/" } ``` ### Delete Card Delete a single card by id |Method|Path| |------|-----------------| |`DELETE`|`/cards/:id`| Insert bearer token for authorization. **Response** | Status Code | Description| |------|-----------------| | **204 No Content** | Card deleted successfully | | Status Code | Description| |------|-----------------| | **404 Not Found** | Card not found | Body ``` { "message": "Card cannot be found", "code": "card_not_found", "errors": [], "timestamp": "2019-10-16T07:38:51Z", "resource": "/api/v1/card/" } ``` ### Upload image upload an image for card and card theme |Method|Path| |------|-----------------| |`POST`|`/image_uploads`| Insert bearer token for authorization. **Request** ``` content type = form data file = image binary ``` **Response** | Status Code | Description| |------|-----------------| | **200 OK** | Image uploaded successfully | Body ``` { "originalName": "phone.jpg", "mimeType": "image/jpeg", "url": "https://betacard.s3.amazonaws.com/2020/01/06/1b449c90-6e65-471a-807c-c0e5cf95dab0.jpg", "user": { "createdAt": "2019-11-12T09:07:14Z", "updatedAt": "2019-11-12T09:07:14Z", "id": 4, "phoneNumber": "+601119724552" }, "id": 1, "createdAt": "2020-01-06T03:44:22Z" } ```