Voucherify builds and maintains REST API documentation and SDKs to make it easier for software developers to understand and integrate Voucherify into their e-commerce platforms.
This document describes all deliverables and their development process.
Voucherify's dev experience is built based on three main items:
- Guides documentation that describes key concepts, integration with Voucherify development and common recipes. This documentation is available on the page: https://docs.voucherify.io/docs.
- API Reference documentation describing REST API endpoints, including available parameters and responses. This documentation is available on the page: https://docs.voucherify.io/reference/introduction-1
- SDKs - clients for all major programming languages, e.g., JavaScript, Java, Ruby, Python, .NET, PHP. SDK's source codes are hosted on the GitHub platform and available for the developers in language-specific package repositories like https://npmjs.com/, https://rubygems.org/ or https://maven.apache.org/
Guides and API Reference pages are hosted on readme.io, the platform for creating and hosting developer documentation. Still, the source of documentation content is stored in the GitHub repository: https://github.com/voucherifyio/voucherify-openapi. Guides are stored purely as markdown files in the https://github.com/voucherifyio/voucherify-openapi/tree/master/docs/guides folder and can be easily uploaded to the readme.io platform via readme CLI. API Reference pages are built by readme.io, which combines the OpenAPI file that describes Voucherify API endpoints, parameters and responses with markdown files from https://github.com/voucherifyio/voucherify-openapi/tree/master/docs/reference-docs folder.
API Endpoint Pages like https://docs.voucherify.io/reference/get-voucher describe REST API endpoint, including details like path, HTTP method, path params, body params, response schema and response statuses. On the right side of those pages, we have a Playground Widget
that allows developers to make test API calls. Readme.io builds those pages using information about the REST API from the uploaded OpenAPI file and displays a UI that allows the exploration of all details. For each endpoint page, we have a corresponding dummy markdown file like https://github.com/voucherifyio/voucherify-openapi/blob/master/docs/reference-docs/VOUCHERS-API-Get-Voucher.md that allows us to control visual aspect of the page displayed in the readme, in particular:
- The markdown attributes section at the beginning of the file wrapped by
---
describes the page title, type, slug, order, and visibility. [block:html]
section that adds custom styles to the page that hides unnecessary UI elements like Playground language selector or expandable readme object exploration widget. It also can be used to display the "Beta" tag next to the title.
Reamde.io platform compares the operationId
endpoint details attribute from the OpenAPI file with the slug
from the markdown attributes to combine it and display the final version of the API Endpoint Page.
As you can notice, all API Endpoint pages are grouped by sections like Vouchers API
, Campaigns API
or Promotions API
. Those sections are built by reamde.io based on the tags
endpoint details attribute from the OpenAPI file and must be repeated in the parentDocSlug
attribute of the dummy markdown file.
Data model pages like: https://docs.voucherify.io/reference/voucher-object describe the schema of the main building blocks used in specific sections. There are two types of Data Model Pages:
- using readme.io expandable object exploration widget, like on the page: https://docs.voucherify.io/reference/validation-object
- displaying schema of the object wit all attributes in a table like on the page: https://docs.voucherify.io/reference/voucher-object
We believe that displaying object details in a table is more intuitive for developers. Unfortunately, readme.io does not have the feature to display building block objects defined in OpenAPI in a table format, so we have built custom JS scripts (build-md-tables-from-openapi
and update-md-tables-in-doc
) that generate markdown tables automatically using an OpenAPI file and put them inside the markdown inside the reference-docs
folder, e.g.: https://github.com/voucherifyio/voucherify-openapi/blob/master/docs/reference-docs/VOUCHERS-API-Voucher-Object.md. Once we generate the markdown files we can upload them to readme.io using the readme.io CLI.
Pages from the introduction section, like https://docs.voucherify.io/reference/introduction-1, are just markdown pages uploaded to readme.io using CLI. Content can be found along with other markdown files inside the docs/reference-docs
folder, e.g. https://github.com/voucherifyio/voucherify-openapi/blob/master/docs/reference-docs/Introduction.md.
To label the API endpoint as a beta in readme.io, you should make the following changes in the corresponding markdown file:
- add
[Beta]
postfix in page title (title
markdown attribute) - add to
[block:html]
section following style:
h1::after {\n content: \"BETA\";\n background-color: rgb(237, 117, 71);\n color: rgb(255, 255, 255);\n border-radius: 2rem;padding: 8px 13px 8px;\n white-space: nowrap;font-size:12px;\n}
OpenAPI syntax documentation can be found here: https://swagger.io/specification/. Voucherify OpenAPI is located here: https://github.com/voucherifyio/voucherify-openapi/blob/master/reference/OpenAPI.json. We use stoplight to edit the OpenAPI file as it gives a nice UI that helps to edit this 80k+ line of code json file. Everyone can create a free account on the Stoplight platform.
How to edit OpenAPI file:
- upload OpenAPI to the Stoplight platform
- make changes in OpenAPI using Stoplight UI
- export modified OpenAPI content and update the OpenAPI file in the repository
- run
npm run remove-stoplight-tags-from-openapi
command to remove from OpenAPI unwanted Stoplight tagsx-stoplight
(that makes it hard to review changes) - ensure that OpenAPI has only expected modifications
[!WARNING] Each OpenAPI change should be tested by reviewing documentation on readme.io after the full documentation update process.
Building new models, we should follow the following name convention:
- Use pascal case casing.
- If a model is used as a specific API endpoint description (0-level model), then we follow the pattern:
{Resource}{Action}{Request|Response}{Body|Query}
, where:Resource
: plural name taken from API path, e.g.Vouchers
,Customers
,Products
Action
:Get
(single record),List
,Update
,Delete
,Create
(etc.)
- If a 0-level model has dedicated sub-models, then those model's names should follow the pattern:
{Resource}{Action}{Differentiator}{Request|Response}{Body|Query}
where theDifferentiator
describes the child model, e.g.:Discount [VouchersValidateDiscountRequestBody]
Gift [VouchersValidateGiftRequestBody]
Loyalty [VouchersValidateLoyaltyRequestBody]
- If a model is used by more than one API endpoint (general model), we use simple domain language, e.g.
Customer
,Category
,Discount
,DiscountUnit
- If a portion of a model is used by more than one schema, we can save this portion under a new schema and use it with
allOf
operator:
{
"GiftCardTransaction": {
"title": "Gift Card Transaction",
"description": "List of gift card transactions",
"anyOf": [
{
"title": "Redemption",
"allOf": [
{
"$ref": "#/components/schemas/GiftCardTransactionBase"
},
{
"$ref": "#/components/schemas/GiftCardTransactionRedemptionDetails"
}
]
},
{
"title": "Refund",
"allOf": [
{
"$ref": "#/components/schemas/GiftCardTransactionBase"
},
{
"$ref": "#/components/schemas/GiftCardTransactionRefundDetails"
}
]
}
]
}
}
For example:
- The general voucher model, used in many different API endpoints, should have the name
Voucher
(currently, it has a name:1_obj_voucher_object
) - for path
GET /v1/vouchers
(list vouchers), we have a1_res_vouchers_GET
0-level model, that should be named:VouchersListResponseBody
. - for path
GET /v1/vouchers
(list vouchers), we have a1_res_vouchers_GET
0-level model which has sub-model1_obj_voucher_object_list_vouchers
that should be named:VouchersListItemResponseBody
- General model
1_obj_voucher_object
is used in many paths (GET /v1/vouchers/{code}
,POST /v1/vouchers/qualification
,GET /v1/publications/create
); therefore, we should rename the model toVoucher
.
[!NOTE] Most likely general model will be same as used in GET method. For example
CategoriesGetResponseBody
is equal by ref toCategory
. This model most likely will not be used inPUT
requests because, response inPUT
request always returns value inupdated_at
, so you will need to create a duplicated model just for update response.
Good practices:
- for literal unions use
enum
- for types unions, use
anyOf
, - for attributes that may contain
null
, add"nullable": true
- for dates use
"type": "string", "format": "date-time"
or"type": "string", "format": "date"
- for the object, add the "required" attribute which should contain a list of required attributes in the object
- Install
git
,nodejs
, andnpm
. - Clone repository locally:
git clone https://github.com/voucherifyio/voucherify-openapi
. - Ensure you have the readme.io account with access to the
Voucherify
project (ask your line manager for help). - Install
rdme
tool (readme.io CLI): follow the installation instructions from https://github.com/readmeio/rdme#readme website. - Authenticate
rdme
tool by running:rdme login
command; you can check if it works using the commandrdme whoami
; what should result:You are currently logged in as [email protected] to the voucherify project.
- Copy
.env.example
to.env
and add to this file your personal API Key created in readme.io:dashboard
>configuration
>API Keys
- There are 2 ways to add images to .md files:
- with
[block:image]
component, see example in Quickstart.md - with link declaration, for example
![Welcome Diagram](https://files.readme.io/6070078-welcome-diagram.png "Welcome Diagram")
- with
- At first always point to assets img folder, for example:
![Recent Changes](../../assets/img/guides_getting_started_quickstart_recent_changes_4.png "Recent Changes")
- This path declaration will be automatically updated to url link while during
npm run manage-project
command, but if you don't want to update project data, You can runnpm run readme-upload-missing-images
instead.
- In order to add new category please go to
scripts/manage-project.ts
and edit following fragment (be informed that the order of each category title is important):
const listOfGuideCategories = [
"Getting started",
"Development",
"Building blocks",
"Campaigns Recipes",
"Discounts Recipes",
"Distributions Recipes",
"More",
];
const listOfReferenceCategories = ["Introduction"];
- In order to change categories order please change the order of categories titles in the fragment presented above.
- In order to remove category, simply remove the title from the list. Make sure to remove .md files associated with this
categorySlag
as well.
[!NOTE]
categorySlag
is created from category title by converting title tokebab-case
/dash-case
(all lower case). Example:Campaigns Recipes
->campaigns-recipes
- For each change / pull request, create your copy of the current documentation, where you will test changes.
- Create your own branch from
master
, - Create a draft pull request
- Create your own branch from
- Make changes in the repository following patterns and good practices.
- Run
npm run manage-project -- --vt={your name}-{pull request number} --create
- this will create new version project with your tag number. - Visit url provided at the end of the script run to test changes using preview on readme.io
- If you need to make a change:
- Do changes...
- Run
npm run manage-project -- --vt={your name}-{pull request number} --update
- this will update your version. - Test changes using preview on readme.io
- If needed - REPEAT
- If changes are fine, then:
- Add a note in the changelog.
git commit; git push
- publish PR
- Ensure the changelog was updated.
- Merge master branch to your branch by running
git merge master
- Run
npm run manage-project -- --vt={your name}-{pull request number} --update
to ensure the version is up-to-date. - Test last time changes on readme (you can use the version prepared by the contributor).
- Merge PR to
master
branch - In readme.io, change the current documentation version from
v2018-08-01
tov2018-08-01-deprecated-mm-dd-yyyy
- Change the name of your new release version from
2018-08-01-{your name}-{pull request number}
tov2018-08-01
[!NOTE] Readme.io cache pages for 15 minutes, for only logged out users. If you are logged in, then you will always receive the most recent content.