RESTful APIs
Hypi platform provides APIs with multiple flavors that suit different developers' tastes. The RESTful APIs are no different and at the same time, they were redesigned to abide by the HATEOS code of conduct for better semantics and easier interpretation.
REST APIs conform to the constraints of the REST architectural style and allows for interaction with RESTful web services. The endpoint https://api.hypi.app/rest
allows you to use standard REST-like requests to execute queries against your instance.
Restful APIs include Authentication or CRUD functions like login
,upsert
, delete
,find
and get
.
There could be multiple ways to execute these functions. It allows Hypi developers to take advantage of the flexibility and tuning the APIs to their awesome applications.
Let's work with the Author
and Book
schema again to execute Restful APIs.
type Author {
name: String
age: Int
bestbook: Book
booklist: [Book!]
}
type Book {
title: String
authorid: Int
price: Float
}
Headers for all the RESTful APIs include App Instance Domain as hypi-domain
and application/json
as content-type
.
For CRUD operations, an authorization header is required with Authorization Token
from the instance.
Authentication
Users can login either by a username or an email. Logins can be triggered either by GET
or POST
. It provides an either/or alternative. You may choose the one that suits your need. The end result would be the same.
GET
Login with Username
The first is the login using the username method. Username and Password are provided in the URL as query parameters.
rest/v1/fn/query/login?username=x&password=y&type=query
Note: Replace x and y with actual username and password.
- Request
- Response
$ curl --location --request GET
'/rest/v1/fn/query/login?username=x&password=y&type=query' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"login": {
"hypi": null,
"sessionToken": "eyJhb ...",
"sessionExpires": 1598888479,
"errorCode": null,
"errorMsg": null
}
}
}
Login with Email
The second is the login using the email method. Email and Password are provided in the URL as query parameters.
/rest/v1/fn/query/loginByEmail?email=x&password=y&type=query
Replace x and y with actual email and password.
- Request
- Response
$ curl --location --request GET
'/rest/v1/fn/query/loginByEmail?email=x&password=y&type=query' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"loginByEmail": {
"hypi": null,
"sessionToken": "eyJhb ...",
"sessionExpires": 1598888597,
"errorCode": null,
"errorMsg": null
}
}
}
POST
Authentication can also be performed using the POST method.
Login with Username
The first is the login using the username method. The username and password are provided as input data.
- Request
- Response
$ curl --location --request POST '/rest/v1/login' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json' \
--data-raw '{
"username": "x",
"password": "y"
}'
{
"data": {
"login": {
"hypi": null,
"sessionToken": "eyJhb ...",
"sessionExpires": 1598888836,
"errorCode": null,
"errorMsg": null
}
}
}
Login with Email
The second is again the login using the email method.
- Request
- Response
$ curl --location --request POST '/rest/v1/login' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json' \
--data-raw '{
"email": "x",
"password": "y"
}'
{
"data": {
"loginByEmail": {
"hypi": null,
"sessionToken": "eyJhb ...",
"sessionExpires": 1598888914,
"errorCode": null,
"errorMsg": null
}
}
}
CRUD Operations
The four basic CRUD operations Create, Read, Update, and Delete can be performed using the semantics of Post, Get, Put, and Delete HTTP methods.
The main REST APIs endpoint is https://api.hypi.app/rest/v1
The APIs endpoint can be mapped to resources using the /{aggregate} or /{aggregate}/{identifier} for both GET and DELETE methods. {aggregate}
is the GraphQL type name from your app's schema and {identifier}
is the ID of the object of the GraphQL type.
E.g. https://api.hypi.app/Author/Author1
POST and PUT will capture the identifiers from the GraphQL request body to avoid redundancy.
The RESTful APIs explained herein allow the same functionality as the CRUD operations explained under Hypi Platform CRUD Documentation
Create Data with POST
To create a resource, send a POST request to the /rest/v1
endpoint with the body containing the resource signature as defined by the GraphQL types. The body (--data-raw) contains the data to be inserted in the Author table. The format of the input data is the same as normal Create operation.
- Request
- Response
$ curl --location --request POST '/rest/v1' \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json' \
--data-raw '{
"values": {
"Author": [
{
"hypi": {"id": "Author1"},
"name": "Dan Brown",
"age": 56,
"booklist":[
{
"hypi": {"id": "Author1Book1"},
"title": "Da Vinci Code",
"price": 12.99,
"authorid": 1
},
{
"hypi": {"id": "Author1Book2"},
"title": "The Last Symbol",
"price": 10,
"authorid": 1
}
]
},
{
"hypi": {"id": "Author2"},
"name": "Paulo Coelho",
"age": 70,
"booklist":[
{
"hypi": {"id": "Author2Book1"},
"title": "Alchemist",
"price": 5.99,
"authorid": 2
}
]
}
]
}
}
}'
{
"data": {
"upsert": [
{
"__typename": "Hypi",
"id": "Author1",
"impl": null,
"created": "2021-04-15T04:04:06Z",
"updated": "2021-04-15T04:04:06Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
},
{
"__typename": "Hypi",
"id": "Author2",
"impl": null,
"created": "2021-04-15T04:04:06Z",
"updated": "2021-04-15T04:04:06Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
}
]
}
}
Update data with PUT
To make an update request, the same endpoint and the payload can be used. However, the HTTP method should be PUT
.
- Request
- Response
$ curl --location --request PUT '/rest/v1' \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json' \
--data-raw '{
{
"values": {
"Author": [
{
"hypi": {"id": "Author3"},
"name": "Sudha Murti",
"age": 70,
"booklist":[
{
"hypi": {"id": "Author3Book1"},
"title": "Wise and Otherwise",
"price": 3.99,
"authorid": 3
},
{
"hypi": {"id": "Author3Book2"},
"title": "How I taught my GrandMother to Read",
"price": 2.99,
"authorid": 3
}
]
}
]
}
}
}'
{
"data": {
"upsert": [
{
"__typename": "Hypi",
"id": "Author3",
"impl": null,
"created": "2021-04-15T04:11:57Z",
"updated": "2021-04-15T04:11:57Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
}
]
}
}
Read data with GET using an ID
In order to access a resource with a particular hypi ID, the endpoint /rest/v1
is appended with {aggregate}/{identifier}
where {aggregate}
is the GraphQL type name from your app's schema and {identifier}
is the ID of the object to get. HTTP method should be GET.
E.g. GET /rest/v1/Author/Author3.
This will retrieve the data from Author3 object.
- Request
- Response
$ curl --location --request GET '/rest/v1/Author/Author3' \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"hypi": {
"__typename": "Hypi",
"id": "Author3",
"impl": null,
"created": "2021-04-15T04:11:57Z",
"updated": "2021-04-15T04:11:57Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
},
"name": "Sudha Murti",
"age": 70,
"bestbook": null,
"booklist": [
{
"__typename": "Book",
"hypi": {
"__typename": "Hypi",
"id": "Author3Book1",
"impl": null,
"created": "2021-04-15T04:11:57Z",
"updated": "2021-04-15T04:11:57Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
},
"title": "Wise and Otherwise",
"authorid": 3,
"price": 3.99
},
{
"__typename": "Book",
"hypi": {
"__typename": "Hypi",
"id": "Author3Book2",
"impl": null,
"created": "2021-04-15T04:11:57Z",
"updated": "2021-04-15T04:11:57Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
},
"title": "How I taught my GrandMother to Read",
"authorid": 3,
"price": 2.99
}
]
}
}
}
Read data with ArcQL Filter
GraphQL find
method can be used to access a resource. Append the endpoint /rest/v1 with {aggregate} and pass on the arcql statement as query parameter.
The ArcQL parameter accepts any valid filter supported by ArcQL.
In the below example, arcql=title='Wise and Otherwise
is an arcql filter to retrieve the details of a book with the title Wise and Otherwise
.
- Request
- Response
$ curl --location
--request GET "/rest/v1/Book?arcql=title='Wise and Otherwise'" \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"find": {
"edges": [
{
"cursor": "Author3Book1",
"node": {
"__typename": "Book",
"hypi": {
"__typename": "Hypi",
"id": "Author3Book1",
"impl": null,
"created": "2021-04-15T04:11:57Z",
"updated": "2021-04-15T04:11:57Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
},
"title": "Wise and Otherwise",
"authorid": 3,
"price": 3.99
}
}
],
"pageInfo": {
"hasPreviousPage": false,
"hasNextPage": false,
"startCursor": "FIRST",
"endCursor": "LAST",
"pageLimit": 25,
"previousOffsets": [],
"nextOffsets": []
}
}
}
}
DELETE Data using an ID
In order to delete a resource, enter {aggregate}/{identifier} as explained earlier. HTTP method should be DELETE.
As Author and Book tables are linked with one-to-many references, you will not be able to delete data without unlinking the references. Hence, pass on clearArrayReferences=true
in the query parameter.
Check more about Delete function here.
- Request
- Response
$ curl --location
--request DELETE '/rest/v1/Author/Author1?clearArrayReferences=true' \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"delete": 1
}
}
DELETE data using ArcQL filter
Delete functionality can also be implemeted using ArcQL filter. The arcql query is passed as a query parameter. (arcql=hypi.id='Author2Book1'
) .
- Request
- Response
$ curl --location --request DELETE
"/rest/v1/Book?clearArrayReferences=true&arcql=hypi.id='Author2Book1'" \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"delete": 1
}
}
GraphQL/ArcQL Functions
Any arbitrary GraphQL function like upsert
, find
, or delete
can be triggered using the following endpoint.
- Endpoints:
/rest/v1/fn/\{root}/{fn}
- Replace {root} with either of
query
ormutation
- Replace {fn} with any GraphQL function such as get, find, login, or your own GraphQL function that you defined in your app's schema.
Create Data
POST
can be used to create resources on the server. This is equivalent to calling the Hypi upsert
function in GraphQL. Use the endpoint /rest/v1/fn/mutation/upsert
to create an object.
- Request
- Response
$ curl --location --request POST '/rest/v1/fn/mutation/upsert' \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: whipcord.apps.hypi.app' \
--header 'content-type: application/json' \
--data-raw '{
{
"values": {
"Author": [
{
"hypi": {"id": "Author4"},
"name": "P G Wodehouse"
}
]
}
}
}'
{
"data": {
"upsert": [
{
"__typename": "Hypi",
"id": "Author4",
"impl": null,
"created": "2021-04-15T05:13:27Z",
"updated": "2021-04-15T05:13:27Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
}
]
}
}
Update Data
Similar to POST
,PUT
is used to update/modify existing resources. It is the same thing with the upsert
function that is also used to modify the resource. Hence, the endpoint remains the same.
/rest/v1/fn/mutation/upsert
- Request
- Response
$ curl --location --request PUT '/rest/v1/fn/mutation/upsert' \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: latest.store.hypi.hypi.hypi.app' \
--header 'content-type: application/json' \
--data-raw '{
{
"values": {
"Author": [
{
"hypi": {"id": "Author5"},
"name": "Enid Blyton"
}
]
}
}
}'
{
"data": {
"upsert": [
{
"__typename": "Hypi",
"id": "Author5",
"impl": null,
"created": "2021-04-15T05:14:48Z",
"updated": "2021-04-15T05:14:48Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
}
]
}
}
Read Data
The Read requests discussed above can be rephrased as arbitrary GraphQL functions by using query/get
or query/find
.
Find
The GET
, PUT
, POST
, and DELETE
methods above are all semantics to make the API more familiar and inline with existing common practice. Data can be retrieved using the the find
function passing the aggregate
to the type
query parameter. An arcql query can also be appended to it. Two query parameters can be separated using '&'.
E.g. /rest/v1/fn/query/find?type=Author&arcql=hypi.id='Author5'
Unlike the GET
function, this returns a list of objects matching the filter provided.
- Request
- Response
$ curl --location
--request GET "/rest/v1/fn/query/find?type=Author&arcql=hypi.id='Author5'" \
--header 'authorization: eyJhb ...' \
--header 'hypi-domain: latest.store.hypi.hypi.hypi.app' \
--header 'content-type: application/json'
{
"data": {
"find": {
"edges": [
{
"cursor": "Author5",
"node": {
"__typename": "Author",
"hypi": {
"__typename": "Hypi",
"id": "Author5",
"impl": null,
"created": "2021-04-15T05:14:48Z",
"updated": "2021-04-15T05:14:48Z",
"trashed": null,
"createdBy": "01F2GA50NFXHMYCBDNYFJK1V7R",
"instanceId": "01F3826NNRNXSDPVBMTMD47SCK"
},
"name": "Enid Blyton",
"age": null,
"bestbook": null,
"booklist": null
}
}
],
"pageInfo": {
"hasPreviousPage": false,
"hasNextPage": false,
"startCursor": "FIRST",
"endCursor": "LAST",
"pageLimit": 25,
"previousOffsets": [],
"nextOffsets": []
}
}
}
}
Above sample examples of RESTful APIs can be tested with Postman. Do check out hypi collection of above examples by clicking button below.
Note: You need to provide actual instance domain name and authorization token to run the queries in Postman.
- How to create data using the REST API
- How to update data using the REST API
- How to read data using the REST API
- How to read data with the ArcQL filter using the REST API
- How to delete data using the REST API
- How to delete data with the ArcQL filter using the REST API
- How to login to Hypi App instance using REST API
- How to create a serverless function to login using REST API
- How to use the Python Requests module to interact with REST APIs of Hypi