How to pass an arbitrary number of parameters while adhering to REST principles - api

I have a database with 3 tables: product, category, and xref_product_category. My business logic permits a product to be associated with an arbitrary number of categories (bed, bath, kitchen, etc.). In terms of designing a REST API, what's the best way to establish these relationships?
For some reason I'm hesitant to pass a JSON array of category IDs as a parameter, but I don't really have a good reason not to. I suppose the other option would be to make a series of PUT calls, passing a single parameter each time. What's the most RESTful way to establish multiple relationships like this? Should this be done in a single API call, or in multiple calls?

In REST, the phrase "arbitrary number of parameters" usually means "representation".
The parameters as a whole could most likely be combined into payload content to represent a resource.
So firstly define the schema for the payload, and then you'll have a media type that can be used to represent it. Document the schema and tell the people who will use the API that they can POST or PUT with that content to define your product and its arbitrary relationships to other resources.
Then define the URI for your product resource and how clients will navigate to it from a Cool (entry-point) URI to it.

I would allow the parameters to be passing in any order.

Related

API - do I need the parent resource?

A person can have many reviews. My endpoint to CREATE a new review is:
post /person/{id}/reviews
How about the endpoint to UPDATE a review? I see two options:
Stick to the parent resource: patch /person/{person_id}/reviews/{id}
Only have reviews in the URI: patch /reviews/{id}
I could be sold on using either of them:
It's consistent with the previously defined endpoint, but {person_id} is not needed.
It's 'efficient' as we're not specifying a parameter ({person_id}) that is not really needed. However, it breaks the API convention.
Which one is preferable and why?
The client shouldn't have to know about ids at all. After a client creates the review, the response should include the URI to the new review like this:
HTTP/1.1 201 Created
Location: /person/4/reviews/5
The client now has the full URL to the review, making it completely irrelevant how it looks like and what information is here.
Don't forget that the URL itself is a system to create globally unique IDs, that embed not just it's own unique identity but also information on how to access the data. If you introduce a separate 'id' and 'person_id' field you are not taking advantage of how the web is supposed to work.
In terms of API design, without knowing too much detail about OP's situation I'd walk along these guideposts:
Only have reviews in the URI: patch /reviews/{id}
It's 'efficient' as we're not specifying a parameter ({person_id})
that is not really needed. However, it breaks the API convention
The "efficiency" allows for a more flexible design. There's no existing API convention broken at this point. Moreover, this approach gives you the flexibility to avoid the need of always needing the parent resource ID whenever you display your items.
Stick to the parent resource: patch /person/{person_id}/reviews/{id}
It's consistent with the previously defined endpoint, but {person_id}
is not needed.
The consistency aspect here can be neglected. It's not beneficial to design endpoints similarly to other endpoints just because the previous ones were designed in a certain way.
The key when deciding one way or the other is the intent you communicate and the following restrictions that are put on the endpoint.
The crucial question here is:
Can the reviews ever exist on their own or will they always have a parent person?
If you don't know for sure, go for the more flexible design: PATCH /reviews/{id}
If you do know for sure that it always will be bound to a particular person and never can have a null value for person_id in the database, then you could embed it right into your endpoint design with: PATCH /person/{person_id}/reviews/{id}
By the way, the same is true for other endpoints, like the creation endpoint POST /person/{person_id}/reviews/{id}. Having an endpoint like this removes the flexibility of creating reviews without a person, which may be desirable or not.

RESTful API Design: ID values for "owned" resources

When designing a restful API, resource ownership is a consideration when designing the URIs. In my case, I'm working on an API where two of my entities will be people and addresses. Each person can have more than one address, so in the database they'll be in separate tables.
Normally I just use auto incrementing keys, so each new record adding increases the ID number.
A thought I had was that if I uses this approach, it would effectively produce a URI like this:
/people/11/addresses/52
In that case, person 11 doesn't have 52 addresses. It's just person 11, who has an address with an ID of 52.
The other side of it is whether I would even be using a URI like that. Addresses generally won't be retrieved on their own by the client, but as part of a person object retrieved by a single API call (/people/11 would retrieve all addresses associated with that person).
Anyway, I guess the question here is about best practices. Is it common to see an entity owned by another with ID values like that? What are the general practices with this?
Your method is correct.
Also These are general rules (reference):
- An API is a user interface for a developer - so put some effort into making it pleasant
- Use RESTful URLs and actions
- Use SSL everywhere, no exceptions
- An API is only as good as its documentation - so have great documentation
- Version via the URL, not via headers
- Use query parameters for advanced filtering, sorting & searching
- Provide a way to limit which fields are returned from the API
- Return something useful from POST, PATCH & PUT requests
- HATEOAS isn't practical just yet
- Use JSON where possible, XML only if you have to
- You should use camelCase with JSON, but snake_case is 20% easier to read
- Pretty print by default & ensure gzip is supported
- Don't use response envelopes by default
- Consider using JSON for POST, PUT and PATCH request bodies
- Paginate using Link headers
- Provide a way to autoload related resource representations
- Provide a way to override the HTTP method
- Provide useful response headers for rate limiting
- Use token based authentication, transported over OAuth2 where delegation is needed
- Include response headers that facilitate caching
- Define a consumable error payload
- Effectively use HTTP Status codes
Also there are lots of references on web. This page is a good start.
and these are also useful: slide1, devzone tutorial
You would normally use a resource like: /people/11/addresses/52 when you return the details of an address in a personalised manner for the people entity.
If for example, you have entities: people and office which can have addresses, and for people you want to display only the country and for offices you want to display all the details of addresses.
On the other hand, if you don't need customization you can also use an url like: /address/12 , since it will be easier to cache a response like that.
Addresses generally won't be retrieved on their own by the client,
but as part of a person object retrieved by a single API call
(/people/11 would retrieve all addresses associated with that person).
If this is the case you can leave out the detailed addresses url.
Yes, That's correct way to apply many to many relation in APIs. Just remember to check id2 belongs to id1 when returning the value.
For retrieving all the addresses the correct call is /people/11/addresses. Then you know you have to call a join query.

In SOA architecture should single API do everything or API should be split as multiple action

We have an app which is exposing a RESTful API to a UI for purchasing an item. I have a question regarding API design. Lets say the following action should be taken in order
Item to be chosen for purchase
Next give the address to be delivered to
My question is: should we design a single API which gets both data perform both? Or should we design two API calls - one that creates a purchase record and second that update the address to be delivered to?
The recommended SOA approach is to choose coarse-grained services, which would seem to argue the minimum amount of API calls.
However, from a business point of view, item selection and purchase and item delivery are two very different concerns that should be separate components in your architecture. For item selection, you need to consider things like inventory and pricing. For delivery address, you need to consider user address lists, address validation, shipping, and taxation.
Those two components are not likely to interact much except maybe some external association between an item id and address id. For this reason, I'd recommend two API calls. Functionally, this would also allow your API users do things like update the delivery address without re-purchasing an item, send the bill to one address and the item to another address, etc.
As you state that you design a RESTful API you usually start by designing resources instead of the intended calls. Later on, resource representations can be chosen that include other resources for optimised HTTP request counts.
You might want to choose to proceed the following way:
Model the item list resource (GET - lists all items, POST - allows item creation) /items/
Model the address list resource /addresses/
Model the item instance resource /items/item/resourceId
Model the address instance resource /addresses/address/resourceId
Now all of your resources are available you can think about usage patterns. All your resources are generically available and can be mashed up.
Possible approaches to answer your questions would be:
Extend the item instance resource with the needed address details (coarse grained as lreeder stated)
Model a resource /deliverydetails/ as list and instance resource containing item(s) and address, make the deliverydetails to be queried by item id or whatever your use case fits best
Hope that helps!
Btw. you are automatically following SOA approaches with a Resource Oriented Design. Interfaces will be naturally fitting your business requirements and generic enough to support more advanced use cases.
Here is a good example

RESTfully creating object graphs

I'm trying to wrap my head around how to design a RESTful API for creating object graphs. For example, think of an eCommerce API, where resources have the following relationships:
Order (the main object)
Has-many Addresses
Has-many Order Line items (what does the order consist of)
Has-many Payments
Has-many Contact Info
The Order resource usually makes sense along with it's associations. In isolation, it's just a dumb container with no business significance. However, each of the associated objects has a life of it's own and may need to be manipulated independently, eg. editing the shipping address of an order, changing the contact info against an order, removing a line-item from an order after it has been placed, etc.
There are two options for designing the API:
The Order API endpoint intelligently creates itself AND its associated resources by processing "nested resource" in the content sent to POST /orders
The Order resource only creates itself and the client has to make follow-up POST requests to newly created endpoints, like POST /orders/123/addresses, PUT /orders/123/line-items/987, etc.
While the second option is simpler to implement at the server-side, it makes the client do extra work for 80% of the use-cases.
The first option has the following open questions:
How does one communicate the URL for the newly created resource? The Location header can communicate only one URL, however the server would've potentially created multiple resources.
How does one deal with errors? What if one of the associons has an error? Do we reject the entire object graph? How is that error communicated to the client?
What's the RESTful + pragmatic way of dealing with this?
How I handle this is the first way. You should not assume that a client will make all the requests it needs to. Create all the entities on the one request.
Depending on your use case you may also want to enforce an 'all-or-nothing' approach in creating the entities; ie, if something falls, everything rolls back. You can do this by using a transaction on your database (which you also can't do if everything is done through separate requests). Determining if this is the behavior you want is very specific to your situation. For instance, if you are creating an order statement you may which to employ this (you dont want to create an order that's missing items), however if you are uploading photos it may be fine.
For returning the links to the client, I always return a JSON object. You could easily populate this object with links to each of the resources created. This way the client can determine how to behave after a successful post.
Both options can be implemented RESTful. You ask:
How does one communicate the URL for the newly created resource? The Location header can communicate only one URL, however the server would've potentially created multiple resources.
This would be done the same way you communicate linkss to other Resources in the GET case. Use link elements or what ever your method is to embed the URL of a Resource into a Representation.

how to create a REST api for filtered data

I've been reading a lot and I understand that a REST API maps resources with HTTP verbs. That's very easy of understand when, for example, a tutorial show an example like Employee.
A PUT will be a new record (if it doesn't exist) or an update; a GET will extract a list with all employees, and a GET api.example.com/employee/12 will extract the record for the Employee with ID = 12.
But, for example, how I could map a more useful queries like "get me all the employees with a salary under 50.000, with less that 2 years at the company and with the marital status as single"?
In other words, how I could parametrize the query? Is it correct to add parameters like api.example.com/Employee?salary<50000&years<2&marital-status=single" ?
The theory:
If you add parameters to your query, they are just part of the URL. The form of the URL does not tell you anything about whether your API is RESTful. Your API with query strings is restful if it obeys the constraints described here: http://en.wikipedia.org/wiki/Representational_state_transfer and (optionally) follows the guiding principles
So as long as your query parameters don't do anything crazy like randomly change the state of some of the resources, then your API is still RESTful
The practice:
Any sensible REST API will need query parameters for the 'index' route. In practice, LinkedIn's REST API has query parameters that just select fields from someone's profile. In this case, the URLs looks completely different from yours, but still obey the principles of REST.
Your situation:
Your query strings can't contain inequalitites, only key+value pairs. You need to express it more like ?max-salary=50000&max-years=2&marital-status=single". You might also name your 'index' route differently: api.example.com/employees (plural)