My questions are based on this article: should-restful-apis-include-relationships
Let's say I have the following resources: users and roles
A single user can be retrieved by api/users/{userId} and a single role by api/roles/{roleId}
The response data of a single user looks like this:
Id: 1
Firstname: Alice
Lastname: Henderson
Email: alice#henderson.com
Roles: api/users/1/roles
To get the roles of this user the application needs to call the returned url api/users/1/roles
For displaying 1 user this approach seems to be ok. But if I want to display all users with their corresponding roles the application needs 1 call to api/users and x calls to api/users/x/roles
How can this design be improved for retrieving multiple users and resolving their role relationships?
You can design your API to accept one or more query parameters which specify the detail level you desire. For instance:
GET /api/users/1?expand=role(self, id, name)
{
"id": 1
"firstName": "Alice"
"lastName": "Henderson"
"email": "alice#henderson.com"
"roles": [
{
"self": "api/roles/4"
"id": 4
"name": "Administrator"
},
{
"self": "api/roles/7"
"id": 7
"name": "Uberuser"
}
]
}
Related
Is there a way to get a more detailed hotel description?
For example, by using this endpoint https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-hotels?hotelIds=ACPAR419 I'm getting such a response
{
"data": [
{
"chainCode": "AC",
"iataCode": "PAR",
"dupeId": 700140792,
"name": "LE NOTRE DAME",
"hotelId": "ACPAR419",
"geoCode": {
"latitude": 48.85306,
"longitude": 2.34654
},
"address": {
"countryCode": "FR"
}
}
],
"meta": {
"count": 1,
"links": {
"self": "https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-hotels?hotelIds=ACPAR419"
}
}
}
What I exactly need: After getting a hotel list from the search, allow the user to open the Hotel details page of one of the found hotels and get more detailed information (Long description, images, rooms, amenities, reviews,). But the above-mentioned endpoint does not provide such a piece of information, only "Hotel name" and a few other fields. Should I combine more than one endpoint or there is already such a service and I just can't see it?
Hotel Booking flow with Amadeus Self-service APIs is with 3 steps :
Step 1: Find all available hotels in a given city or location using
Hotel List API
Step 2: Find the available prices with room details, descriptions and more using Hotel Search API
Step 3: Complete the booking engine using Hotel Booking API
https://developers.amadeus.com/blog/build-hotel-booking-engine-amadeus-api
with the updated version of Hotel Search V3.0, unfortunately, the information on hotel image/address/contact details/rating/amenities is missing.
https://amadeus4dev.github.io/developer-guides/migration-guides/hotel-search/#search-hotels-by-a-city-or-geocode
I'm using amazon-cognito for my application user access.
I have two different groups inside my user pool.
I want to send differenet email to each user depends on the group he belongs to.
The problem is that the email verification is sent when the user is created at the pool and not after he's linked to a group.
Is there a way do to it?
Any help? advices?
After a lot of digging, I've figured out a solution.
The solution is to use AWS Cognito Lambda.
Use AWS Cognito Lambda for SignUp or AdminCreateUser events depends on your application architecture.
When a user is created either with SignUp or AdminCreateUser functions, there's an option to pass metadata with clientMetadata entry at the object.
For example (from AWS Docs):
{
"ClientMetadata": {
"string" : "string"
},
"DesiredDeliveryMediums": [ "string" ],
"ForceAliasCreation": boolean,
"MessageAction": "string",
"TemporaryPassword": "string",
"UserAttributes": [
{
"Name": "string",
"Value": "string"
}
],
"Username": "string",
"UserPoolId": "string",
"ValidationData": [
{
"Name": "string",
"Value": "string"
}
]
}
According to docs:
clientMetadata
One or more key-value pairs that you can provide as
custom input to the Lambda function that you specify for the pre
sign-up trigger. You can pass this data to your Lambda function by
using the ClientMetadata parameter in the following API actions:
AdminCreateUser, AdminRespondToAuthChallenge, ForgotPassword, and
SignUp.
So, pass the group inside the clientMetadata as an entry:
"ClientMetadata": {
"Group": "MyNiceGroup"
},
...
Inside the lambda implementation, according to the incoming group decide which email to dispatch.
I am new to Dialogflow so my question may be too simple. However, I do not understand what is the purpose of naming actions in Dialogflow. I have watched videos on youtube and people in them are using actions when they have a webhook. For example they may have an if condition in their source code
(e.g. in python
if action == 'action_name':
...
)
which executes something particular in this case.
However the json output which is retrieved by the source code has the following form:
{
"id": "123d9e8e-314f-451b-8b15-5e3b55baa980",
"timestamp": "2018-03-16T17:03:05.987Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "Hello",
"action": "input.welcome",
"actionIncomplete": false,
"parameters": {},
"contexts": [],
"metadata": {
"intentId": "effe6b2b-3372-4f89-882f-ff937b2b2abb",
"webhookUsed": "false",
"webhookForSlotFillingUsed": "false",
"intentName": "Welcome"
},
"fulfillment": {
"speech": "Hello, how can I help you?",
"messages": [
{
"type": 0,
"speech": "Hello, how can I help you?"
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "491d57cb-0af2-45ac-a658-9e47ec6658ce",
"alternativeResultsFromKnowledgeService": {}
}
Since the json data contains the IntentName why to bother naming an unique action for this specific intent when you can get directly the name of the intent in your json?
I tend to think of this in two ways, depending on exactly what I'm building. (Or sometimes a combination of these two ways.)
The Intent Name is a human-usable name, while the Action is something that is more intended for use by the webhook and more directly maps to a function.
Since you can have more than one Intent use the same Action, it can be convenient to map a few different ways the user may say something (and the parameters they may send along with them) to the same method. While you could do that by listing all the different Intent names in your code, it is easier to do that on the Dialogflow side.
In truth - use whatever works best for you. I tend to name my Intents and my Actions very similarly, but do branching based on what makes the most sense for the code (which sometimes also includes other values that may be sent).
I have a page where I list the books of a school. The user can update a book, add a new book or delete an existing book. All actions must be saved when the form is submitted.
How can i map a rest API for that? I could take advantage of the endpoints i already have.
UPDATE
PUT /schools/1/books
{
"books": [
{
"id": "1",
"name": "Book 1"
}
]
}
CREATE
POST /schools/1/books
{
"books": [
{
"name": "Book 2"
},
{
"name": "Book 3"
}
]
}
DELETE
DELETE /schools/1/books
{
"books": [
{
"id": 2
}
]
}
But I need everything to run on the same transaction, and wouldn't make sense to submit 3 requests.
I also thought of creating a new endpoint where I would create books that doesn't exists, update books that exists, and remove books that are not present on the request.
So if this school has Book 1 and Book 2, I could update Book 1, create New Book and remove Book 2 with:
PUT /schools/1/batch-books
{
"books": [
{
"id": "1",
"name": "Updated Book 1"
},
{
"name": "New Book"
}
]
}
Do you guys have other options?
I would separate things into different resources:
/books and /books/{id} for books. They gives book details and allow to manage them.
/schools and /schools/{id} for schools. They gives school details and allow to manage them.
/schools/{id}/books to associate books in schools. I mean books that are available within a school. This resource provides methods to manage a list of links to books.
Let me detail the last resource. In fact, this is related to hypermedia. In the following, I'll use JSON-LD but you're free to use other hypermedia tools.
A GET method will return the list of associated books:
GET /schools/1/books
[
{
"#id": "http://api.example.com/books/1895638109"
},
{
"#id": "http://api.example.com/books/8371023509"
}
]
You can notice that you can implement mechanisms to allow to get more details if needed. Leveraging the Prefer header seems to be a great approach (see the link below for more details).
In addition, you could provide the following methods:
POST to add a link to the school. The request payload would be: {"#id": "http://api.example.com/books/1895638109"}. The response should be a 201 status code.
DELETE to delete a specific link from a school. A query parameter could be used to specify which link to remove.
PATCH to allow to do several operations in one call and actually provide some batch processing. You can leverage at this level JSON-PATCH for the request processing. Within the response, you could describe what happens. There is no specification at this level so you're free to use what you want... Here is a sample for the request payload:
PATCH /schools/1/books/
[
{
"op": "add", "value": "http://api.example.com/books/1895638109"
},
{
"op": "remove", "path": "http://api.example.com/books/8371023509"
}
]
Reading the following links could give you some hints on the way to design such use case:
Implementing bulk updates within RESTful services: http://restlet.com/blog/2015/05/18/implementing-bulk-updates-within-restful-services/
On choosing a hypermedia type: http://sookocheff.com/post/api/on-choosing-a-hypermedia-format/
Creating Client-Optimized Resource Representations in APIs: http://www.freshblurbs.com/blog/2015/06/25/api-representations-prefer.html
Hope it helps you,
Thierry
I'm trying to design a relationship between two different resources with dependency. The scenario is:
Two resources, the first one called "account" and the second one called "person".
In my API the "person" resource is a representation of a person in real world, with name, age, gender, address, telephone, etc. Account is the resource responsible to authenticate a person, like a login.
So the representation of "person" resource looks like below:
{
"id": "7828292",
"name": "Joseph Climber",
"email": "yourmail#email.com",
"gender": "M",
"telephones": {
"main": {
"number": "898987777"
},
"secondary": {
"number": "909099090"
},
"business": {
"number": "937363902"
}
},
"address": {
"rel": "address",
"href": "person/{ID}/address"
}
}
And the representation of "account" resource looks like:
{
"id": "login#email.com",
"tokenAccess": "5E69FAE25F4B4F3E8CC5DE09A8163520",
"link": {
"rel": "person",
"href": "person/{id}"
}
}
My problem is: when I create a new person (POST person) I don't have a way to authenticate the new person, in this case is necessary to create a new account to do this, so this seems a little bit confusing for the API consumers, because the API doesn't express this kind of relationship naturally (basic concept of a good API design).
What is the best way to represent this dependency between account and person resource?
Maybe if someone attempts to POST to /person without an access token, then return a status code 401 Unauthorized with a body something like:
{
"#type": "error",
"description": "You must be authenticated to POST to person. If you do not have an account, then POST to /account to get an access token."
}
I imagine that would be intuitive enough for developers using the API.