The purpose of this documentation is to detail principles, objects, behaviours and error handling for the AkaboxiBackend API.
This API has been developed to enable as a backend interface for all Akaboxi management systems / applications.
All endpoints must come after this URI:
# /api/v2/admin
. Forexample,https://server.com/api/v2/admin/ENDPOINT
.All other requests hitting the endpoint directly will be rejected with a404
(Not Found)
The API has been built using NodeJS and you will be required to install Yarn or NPM inorder to access the required dependencies.
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https: //dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
Test that Yarn is installed by running:
yarn --version
You need to head cd
into the home directory and run:
yarn start
To run tests, you need to have a test database installed and running on the machine you intend to install this API. This is because, before tests run, the test database is brought down and migrations and seeds are re-run.
To run tests:
yarn test
For all requests made to any of the endpoint herein, you're advised to wrap them in try/catch
blocks taking advantage of the awesome ES6 async/await
syntax. This reduces on the .then(), .catch()
chain length.
AJAX Libraries such as axios is a very good promise based HTTP client for the browser
and node.js
.
Eg:
// Send a POST request
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
- Configuring Axios
You need to configure axios as a separate module. This could be named http-common.js
import axios from 'axios';
import $store from './vuex-store';
const token = $store.state.token;
export const HTTP = axios.create({
baseURL: `https://example.com/system/`,
timeout: 1000,
headers: {
Authorization: 'Bearer {token}'
}
});
- Sample Axios Request
In your component (Used Vue) for this example. We are making a GET
request to the /savings endpoint.
<script>
import {HTTP} from './http-common';
export default {
data() {
return {
data: [],
errors: []
}
},
async created() {
try{
const response = await HTTP.get(`savings`);
this.data = response.data;
// HTTP.post('https://site.com/', {
// name: 'Any Name'
// })
} catch(error) {
this.errors.push(error);
}
}
}
</script>
All
POST
methods expect valid body objects as described below. Should you send an incomplete body, malformedjson
or a missing body request, the server will reject all these with anInvalid Input!
error.
-
Code: 403 | 500
-
Content:
Various errors might come back from the server. They will be wrapped in the response body object like below. Please be keen on catching these errors.
{
"error" : "--message--",
}
- Who Is A Super Admin?
A super admin is a user at the topmost level of the whole akaboxi web and mobile management systems / applications
. By logging in, he is authenticated to access the Main Administration system including but not limited to, registering organisations and groups, members(* secretaries *), managing these organisations.
POST Method to Login.
- Endpoint
/super-login
-
Method:
POST
-
Body:
{
"email" : "[email protected]",
"password" : "some-random-password"
}
Upon successful request, the server responds with a 200 OK
status code.
-
Success Reponse:
-
Code: 200 OK
-
Content:
-
{
"user": {
"id": 1,
"fname": "John",
"sname": "Doe",
"gender": "Male",
"usertype": "sadmin",
"createdAt": "2019-04-26T12:27:27.000Z",
"updatedAt": "2019-04-26T12:27:27.000Z",
"email": "[email protected]"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZm5hbWUiOiJKb2huIiwic25hbWUiOiJEb2UiLCJnZW5kZXIiOiJNYWxlIiwidXNlcnR5cGUiOiJzYWRtaW4iLCJjcmVhdGVkQXQiOiIyMDE5LTA0LTI2VDEyOjI3OjI3LjAwMFoiLCJ1cGRhdGVkQXQiOiIyMDE5LTA0LTI2VDEyOjI3OjI3LjAwMFoiLCJlbWFpbCI6ImFrYWJveGlAYWthYm94aS5jb20iLCJpYXQiOjE1NTY5MDc3MzgsImV4cCI6MTU1NjkxMTMzOH0.d91lHqW0rugHeszRns6pd3kgPPO4_of0KRGPP_ygK3g",
"roles": {
"id": 1,
"role_name": "SuperAdmin",
"createdAt": "2019-04-26T12:27:27.000Z",
"updatedAt": "2019-04-26T12:27:27.000Z"
}
}
-
You are advised to save this token to some flux stores eg.
Vuex
,Redux
or other webstorage resources likeLocalStorage
and always set this aBearer token
inauthorization
headers on any other subsequent requests made to the server. This is the only way to authenticate whether information coming from the server is being seen received, viewed and used by the person intended. -
This authentication token is generated to be valid for a session period of
1 hour
, users will be requested to re-authenticate themselves thereafter. You are therfore advised to try and catch anyAuthentication Failed
error responses to provide meaningful error messages to the user and help them redirect to the Login page. -
This server generated token is always going to be unique on every other authentication request. Remember to clear it from where it is stored after Logging the User Out.
Here we deal with being able to create an Organization, quering for one or more than one Organization and Edit the Organizations profile.
An organization owns groups
To create a new Organization.
-
Endpoint /add-organization
-
Method:
POST
-
Body:
{
"name" : "akaboxi Fund",
"address" : "Semawata Rd.",
"email" : "<[email protected]>",
"website" : "WWW.AKABOXI.COM",
"telephone" : "0789776655",
"description" : "Kiryandongo Saving Groups",
"org_role_id" : 1
}
The organization role id org_role_id is automatically asigned based on payment plan an organization belongs to either Basic or Premium.
- Success Reponse:
- Code: 200 Success
- Content:
{
"id": 1,
"name" : "Akaboxi Fund",
"address" : "Semawata rd.",
"email" : "<[email protected]",
"website" : "www.akaboxi.com",
"telephone" : "0789776655",
"description" : "Kiryandongo saving groups",
"org_role_id" : 1,
"updateAt" : "2019-04-25T15:47:07.648Z",
"createAt" : "2019-04-25T15:47:07.648Z"
}
To fetch one Organization.
-
Endpoint /organization/:id
-
Method:
GET
-
URL Params ..* Required:
id = [interger]
-
Success Response:
- Code: 200 Success
- Content:
{
"id": 1,
"name": "Max Children Fund",
"address": "Najjera St.",
"email": "[email protected]",
"website": "www.maxchil.com",
"telephone": "0789776655",
"description": "Najjera Saving Groups",
"org_role_id": 1,
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-04-26T12:27:28.000Z"
}
GET Method to fetch all Organizations.
- Endpoint /organizations-list/:page
where:
[page] - current page (default 0) and will return the first 25 records.
-
Method:
GET
-
Success Response:
- Code: 200 Success
- Content:
{
"totalOrganizations": 2,
"organizations": [
{
"id": 2,
"name": "Testing Children Fund Updated",
"address": "Najjera, Bulabira",
"email": "[email protected]",
"website": "www.maxchil.com",
"telephone": "0789776655",
"description": "Najjera Saving Groups",
"org_role_id": 2,
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-04-26T12:27:28.000Z",
"role_name": "Premium-Plan"
},
{
"id": 2,
"name": "Max Children Up",
"address": "Updated Address",
"email": "[email protected]",
"website": "www.maxchil.com",
"telephone": "0789776655",
"description": "Najjera Saving Groups",
"org_role_id": 2,
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-04-26T12:27:28.000Z",
"role_name": "Premium-Plan"
}
]
}
To update an Organization's bio-information.
-
Endpoint /organization/:id
-
Method:
PUT
-
Body
{
"name" : "Max Children Updated",
"address" : "Updated Address Updated",
"email" : "<[email protected]",
"website" : "www.maxchil.com",
"telephone" : "0789776655",
"description" : "Najjera saving groups",
"org_role_id" : 1
}
- Success Response:
- Code: 200 success
- Content:
{
"id": 1,
"name": "Testing Children Fund Updated",
"address": "Najjera, Bulabira",
"email": "[email protected]",
"website": "www.maxchil.com",
"telephone": "0789776655",
"description": "Najjera Saving Groups",
"org_role_id": 2,
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-05-10T13:04:13.000Z"
}
Create a group, view one created, edit a group, view group members, and others as seen hereafter.
A group houses members
To create a new group.
-
Endpoint /add-group
-
Method:
POST
-
Body:
{
"group_name": "Testing kirya-Group",
"description": "Testing Kiryandongo group",
"organ_id": 1
}
where [organ_id] is the organization where this group belongs. This must exist or else the server will respond with an error.
- Success Reponse:
- Code: 200 Success
- Content:
{
"id": 9,
"group_name": "Testing kirya-Group",
"description": "Testing Kiryandongo group",
"organ_id": 1,
"updatedAt": "2019-05-10T14:25:18.523Z",
"createdAt": "2019-05-10T14:25:18.523Z"
}
To update a new group.
-
Endpoint /groups/:id
-
Method:
PUT
-
Body:
{
"group_name": "Testing kirya-Group Updated",
"description": "Testing Kiryandongo group Three",
"organ_id": 1
}
where [organ_id] is the organization where this group belongs. This must exist or else the server will respond with an error.
- Success Reponse:
- Code: 200 Success
- Content:
{
"id": 9,
"group_name": "Testing kirya-Group Updated",
"description": "Testing Kiryandongo group Three",
"organ_id": 1,
"status": "active",
"createdAt": "2019-05-10T14:25:18.000Z",
"updatedAt": "2019-05-10T14:26:08.000Z"
}
Get all groups belonging to organization with id: 3.
- Endpoint /groups-list/:organ_id/:page
where:
[organ_id] -id of the organization
[page] - current page (default 0) and will return the first 25 records.
-
Method:
GET
-
Success Reponse:
- Code: 200 Success
- Content:
{
"totalGroups": 3,
"allgroups": [
{
"id": 1,
"group_name": "kirya-Group No.3-updated",
"description": "Kiryandongo group Three-updated",
"organ_id": 2,
"status": "active",
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-05-08T17:27:30.000Z"
},
{
"id": 2,
"group_name": "kirya-Group No.2",
"description": "Kiryandongo group Two",
"organ_id": 2,
"status": "active",
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-04-26T12:27:28.000Z"
},
{
"id": 7,
"group_name": "kirya-Group No.3",
"description": "Kiryandongo group Three",
"organ_id": 2,
"status": "active",
"createdAt": "2019-04-26T12:37:55.000Z",
"updatedAt": "2019-04-26T12:37:55.000Z"
}
]
}
Get one group's bio data.
- Endpoint /groups/:id
where:
[id] -id of the group
-
Method:
GET
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 9,
"group_name": "Testing kirya-Group Updated",
"description": "Testing Kiryandongo group Three",
"organ_id": 1,
"status": "active",
"createdAt": "2019-05-10T14:25:18.000Z",
"updatedAt": "2019-05-10T14:26:08.000Z"
}
Delete a group.
- Endpoint /groups/:id
where:
[id] -id of the group
-
Method:
PATCH
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 1,
"group_name": "kirya-Group No.3-updated",
"description": "Kiryandongo group Three-updated",
"organ_id": 2,
"status": "inactive",
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-05-08T17:26:48.000Z"
}
Make a group active again
- Endpoint /reactivate-group/:id
where:
[id] -id of the group
-
Method:
PATCH
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 1,
"group_name": "kirya-Group No.3-updated",
"description": "Kiryandongo group Three-updated",
"organ_id": 2,
"status": "active",
"createdAt": "2019-04-26T12:27:28.000Z",
"updatedAt": "2019-05-08T17:27:30.000Z"
}
Set An Interest Rate for every group registered.
- Endpoint /group-settings/:id
where:
[id] -group's id
- Body:
{
"rate": 5
}
-
Method:
PUT
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 9,
"group_name": "Testing kirya-Group Updated",
"description": "Testing Kiryandongo group Three",
"organ_id": 1,
"status": "active",
"settings": "5",
"createdAt": "2019-05-10T14:25:18.000Z",
"updatedAt": "2019-05-20T17:53:18.000Z"
}
Get all members belonging to a group in a certain organization.
- Endpoint /group-members/:id/:page
where:
[organ_id] -id of the group
[page] - current page (default 0) and will return the first 25 records.
-
Method:
GET
-
Success Reponse:
- Code: 200 Success
- Content:
{
"totalMembers": 1,
"members": [
{
"id": 1,
"picture_id": "userImage-1556799101234.jpg",
"occupation": "Peasant",
"mem_role": "secretary",
"address": "Metropolitan city, kampala",
"status": "active",
"user_details_id": 5,
"groups_group_id": 1,
"account_id": "34345SDBC",
"date_of_birth": "1992-01-01",
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-02T12:11:41.000Z",
"user_detail": {
"id": 5,
"fname": "Akampa",
"sname": "Moses",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-02T11:33:49.000Z"
}
}
]
}
Create a member, view one created, edit a member's info, and others as seen hereafter.
A must be attached to a group
To create a new member.
-
Endpoint /add-member
-
Method:
POST
-
Body:
{
"user_detail": {
"fname": "Businge",
"sname": "Merimack",
"gender": "Male",
"usertype": "member"
},
"gen_info": {
"occupation": "peasant",
"mem_role": "secretary",
"address": "Makombo, Kampala",
"groups_group_id": 2,
"account_id": "343GHDDDBC",
"date_of_birth": "1993-01-01"
},
"next_of_kin": {
"user_detail": {
"fname": "Nuwasiima",
"sname": "Gordon",
"gender": "Male",
"usertype": "nxt_kin"
},
"relationship": "Brother"
}
}
Kindly note that all this is required. You're supposed to tweek your frontend Ajax library to be able to generate this kind of object in the same format as seen above. As put before, malformed json objects will result in errors.
- Success Reponse:
- Code: 200 Success
- Content:
{
"member": {
"id": 11,
"fname": "Businge",
"sname": "Merimack",
"gender": "Male",
"usertype": "secretary",
"updatedAt": "2019-05-02T12:29:28.412Z",
"createdAt": "2019-05-02T12:29:28.412Z"
},
"next_of_kin": {
"id": 12,
"fname": "Nuwasiima",
"sname": "Gordon",
"gender": "Male",
"usertype": "nxt_kin",
"updatedAt": "2019-05-02T12:29:28.437Z",
"createdAt": "2019-05-02T12:29:28.437Z"
}
}
To update a new member.
-
Endpoint /members/:id
-
Method:
PUT
-
Body:
{
"user_detail": {
"fname": "Businge Updated",
"sname": "Merimack Updated",
"gender": "Male"
},
"gen_info": {
"occupation": "peasant",
"mem_role": "secretary",
"address": "Makombo, Kampala",
"groups_group_id": 2,
"account_id": "343GHDDDBC",
"date_of_birth": "1993-01-01"
},
"next_of_kin": {
"id": 12,
"user_detail": {
"fname": "Nuwasiima Updated",
"sname": "Gordon",
"gender": "Male"
},
"relationship": "Boss"
}
}
-
It is PARAMOUNT to note that in next_of_kin object, id, refers to user_detail id. and it must be separated from the user_detail as a separate property. Please refer to the example above. Please use it as a format to compose your request body object.
-
Success Reponse:
- Code: 200 Success
- Content:
{
"member": {
"id": 4,
"picture_id": "userImage-1556907765246.jpg",
"occupation": "peasant",
"mem_role": "secretary",
"address": "Makombo, Kampala",
"status": "active",
"user_details_id": 11,
"groups_group_id": 2,
"account_id": "343GHDDDBC",
"date_of_birth": "1993-01-01",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-12T19:17:40.000Z",
"user_detail": {
"id": 11,
"fname": "Businge Updated",
"sname": "Merimack Updated",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-12T19:17:40.000Z"
}
},
"nxtOfKin": {
"id": 3,
"relationship": "Boss",
"member_id": 4,
"user_details_id": 12,
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-12T19:17:40.000Z",
"user_detail": {
"id": 12,
"fname": "Nuwasiima Updated",
"sname": "Gordon",
"gender": "Male",
"usertype": "nxt_kin",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-12T19:17:40.000Z"
}
}
}
Get one members's bio data.
- Endpoint /members/:id
where:
[id] -member id (Not user_details id - IMPORTANT)
-
Method:
GET
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 1,
"picture_id": "userImage-1556799101234.jpg",
"occupation": "Peasant",
"mem_role": "secretary",
"address": "Metropolitan city, kampala",
"status": "active",
"user_details_id": 5,
"groups_group_id": 1,
"account_id": "34345SDBC",
"date_of_birth": "1992-01-01",
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-02T12:11:41.000Z",
"user_detail": {
"id": 5,
"fname": "Akampa",
"sname": "Moses",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-02T11:33:49.000Z"
},
"next_of_kin": {
"id": 1,
"relationship": "Wife",
"member_id": 1,
"user_details_id": 6,
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-02T11:33:49.000Z"
}
}
Members are expected to have a picture associated with their accounts specifically to identify them. This could be a picture (Scanned/Fresh) of their recognised ID.
-
Endpoint /add-member-image
-
Method:
POST
-
Body: The body must be a formdata object. There is a ton of tutorials online showing exactly how to use AJAX to post .jpg, and .png files. Kindly validate locally (from the client side) to make sure only these two types are sent to the server. - user_id is the user's user_details_id.
{
"userImage": "SomeImage.png",
"user_id": 11
}
Kindly note that all this is required. You're supposed to tweek your frontend Ajax library to be able to generate this kind of object in the same format as seen above. As put before, malformed json objects will result in errors.
- Success Reponse:
- Code: 200 Success
- Content:
{
"id": 11,
"fname": "Businge",
"sname": "Merimack",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-03T11:45:15.000Z"
}
Delete a member.
- Endpoint /members/:id
where:
[id] -member's id , not user_details id
-
Method:
PATCH
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 4,
"picture_id": "userImage-1556907765246.jpg",
"occupation": "peasant",
"mem_role": "secretary",
"address": "Makombo, Kampala",
"status": "inactive",
"user_details_id": 11,
"groups_group_id": 2,
"account_id": "343GHDDDBC",
"date_of_birth": "1993-01-01",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-08T17:10:54.000Z",
"user_detail": {
"id": 11,
"fname": "Businge",
"sname": "Merimack",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-03T11:45:15.000Z"
}
}
Re-activate a member's status.
- Endpoint /reactivate-member/:id
where:
[id] -member's id , not user_details id
-
Method:
PATCH
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 4,
"picture_id": "userImage-1556907765246.jpg",
"occupation": "peasant",
"mem_role": "secretary",
"address": "Makombo, Kampala",
"status": "active",
"user_details_id": 11,
"groups_group_id": 2,
"account_id": "343GHDDDBC",
"date_of_birth": "1993-01-01",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-08T17:11:08.000Z",
"user_detail": {
"id": 11,
"fname": "Businge",
"sname": "Merimack",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T12:29:28.000Z",
"updatedAt": "2019-05-03T11:45:15.000Z"
}
}
Set An Access PIN for every member registered.
- Endpoint /set-member-pin/:id'
where:
[id] -member's id , not user_details id
- Body:
{
"PIN": 1234
}
-
Method:
PUT
-
Success Reponse:
- Code: 200 Success
- Content:
{
"id": 1,
"picture_id": "userImage-1556799101234.jpg",
"occupation": "Peasant",
"mem_role": "secretary",
"address": "Metropolitan city, kampala",
"status": "active",
"PIN": "1234",
"user_details_id": 5,
"groups_group_id": 1,
"account_id": "34345SDBC",
"date_of_birth": "1992-01-01",
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-20T15:50:48.000Z",
"user_detail": {
"id": 5,
"fname": "Akampa",
"sname": "Moses",
"gender": "Male",
"usertype": "secretary",
"createdAt": "2019-05-02T11:33:49.000Z",
"updatedAt": "2019-05-02T11:33:49.000Z"
}
}