I have a functional API endpoint
myapi.com/channels/costs
at present with the [GET] call implemented. This endpoint is now in production.
Now, this is for the all the customers in the USA. The same database used by this endpoint also has the relevant details for other countries.
I have requirement to incorporate the same logic/call for UK customers.
Should I use:
1. myapi.com/uk/channels/costs ?
2. (still use) myapi.com/channels/costs & then include a custom header to differentiate between USA and UK?
Is there a prescribed way to do this?
I'd propose you use the same URL with a query parameter (rather than a header) to specify the relevant country, defaulting to USA when not specified. This fits in with the RESTful style of the URI representing a resource that is being queried, and you're querying it slightly differently.
Related
I wanted to get opinion on resource granularity. Say, I have a an domain entity called "magazines". But there are different types of magazines, including Sports, Nature, Automobiles, Computers and Aeroplanes, etc.
When I want to create a new "sports" magazine, should I be using construct such as:
PUT /magazines
PUT /sports-magazines
PUT /magazines/sports
When I want to get a specific sports magazine, should I be saying:
GET /magazines/{id}
GET /sports-magazines/{id}
GET /magazines/sports/{id}
If I want to get sports magazines for the year 2001, should I be using:
GET /magazines?type=sports&year=2001
GET /sports-magazines?year=2001
GET /magazines/sports?year=2001
And finally, if I want to return how many pages each type of magazine has for January 2001 publication, how would I do that? Do I need to create a new pages resource for that? Or make two independent requests or something else? First of these is listed below:
GET /magazines/pages?type1=sports&type2=nature&year=2001&month=01
GET /sports-magazines/pages?type=nature&year=2001&month=01
Given these scenarios how would you model your resources?
I have a an domain entity called "magazines". But there are different types of magazines, including Sports, Nature, Automobiles, Computers and Aeroplanes, etc.
Important thing to understand: resources aren't domain entities. Your resource model is a facade that sits in front of your domain model.
Notice, for example, that this resource (REST API Resource Granularity) describes not only your question, but also my answer.
PUT probably is NOT what you want for "create a new resource" unless the client is already in position to know what URI should be used for the new resource. The target URI of a PUT request is the same URI that we expect to use later to GET the data
PUT /magazines/{id}
GET /magazines/{id}
In the case where we don't expect the client to know what the URI is going to be... well, we don't have an HTTP method that means precisely that, so we fall back to using POST (see Fielding, 2009).
POST /magazines
201 Created
Location: /magazines/12345
Note that the machines don't care if the URI of the created resource(s) match the target URI of the POST request.
REST really doesn't care what spelling conventions you use for your resource identifiers (in much the same way that the machines don't care what spelling conventions you use for variable names).
GET /magazines?type=sports&year=2001
GET /sports-magazines?year=2001
GET /magazines/sports?year=2001
GET /magazines/sports/year=2001
GET /magazines/sports/2001
Those are all fine; there are trade-offs. Key value pairs encoded into a query string make creating URI with HTML forms easier, using path segments makes relative resolution easier.
I want to return how many pages each type of magazine has for January 2001 publication
Creating a new URI with that information is fine. Extending the schema of your existing resources to include that information is also fine.
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.
I'm working on REST Api suing Python Flask, as I have more and more routes, its hard to manage all the resource urls.
Right now, I'm confused which one is better practices of URL parameters. Examples below:
Get a list of courses with limits:
/courses/<int:lim> OR /courses/list?lim=10
Get a specific course:
/courses/<code>/<section> OR /courses/show?code=cs100§ion=1
Get a list of students in specific course:
/courses/<code>/<section>/students OR /students/show?code=cs100§ion=1
Should I pass query parameters using / or by doing ?
The only reason I'm using / is that there's no conflict in query.
If I have these two URL for two different queries, how can I fix it so I can query base on the parameters:
/students/show?code=cs100§ion=1 (Get all students in that course)
/students/show?id=123456789 (Get the specific student)
The URL should identify a resource or collection of resources. Any options you want to give the client, such as pagination, limits, filtering, sorting, etc. I think is best to include in the query string or in HTTP headers.
So regarding your specific questions:
Get a list of courses with limits: /courses/<int:lim> OR /courses/list?lim=10
Neither one. Use /courses?lim=10. No need to have a /list component, that is an action, not a resource.
Get a specific course: /courses/<code>/<section> OR /courses/show?code=cs100§ion=1
The first. Once again, /courses/show indicates an action, you want URLs to be links to resources, in this case your course.
Get a list of students in specific course: /courses/<code>/<section>/students OR /students/show?code=cs100§ion=1
The first, same reason as the previous one.
I have given REST API talks at the last two PyCon conferences, feel free to check them out if you want to learn more API design best practices:
PyCon 2014: Writing RESTful Web Services with Flask
PyCon 2015: Is Your REST API RESTful?
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)
EDIT: I've solved my issues (for now at least).
I've recently been working with the Zendesk REST Api and their use of the custom "X-On-Behalf-Of" header for looking up tickets opened by a particular user got me thinking about Restful Api design choices (in no specific language, more of a how to name URIs question). I've also read this related question on Custom HTTP headers, but it left me with more questions than answers.
Say I have an example restful web service dealing with rental apartment applications where clients use Basic Auth (keep it simple) to authenticate. Define the basic data as such:
Users (can be of type landlord or renter)
Forms (which consist of one or more Document resources and some form meta data like form name and version info)
And then some type of resource corresponding to Rental Applications, which ties together Forms, Applicants (one or more renters), Landlord, and some metadata like status and dates.
I'm struggling to properly model the URIs for the Applications resource in general, and more specifically with respect to a clients role. (assume api root is https://api.example.com/)
How do I allow a Landlord to fetch a list of applications sent to them? My intuition says make a request to "GET /applications" and Basic Auth lets the server know which user to build the list for; likewise "GET /applications" requested by a Renter would return a list of applications they've sent...but I'm not confident this is a solid design in general to mix and match sender vs. recipient lists at the same URI. Should I be thinking about the "/applications" resource differently, and perhaps allowing a hierarchy like "/applications/[USER_IDENTIFIER]" for each user instead?
Also, regardless of my applications URI design, assume a Landlord is able to create an application on behalf of a renter. Is this better accomplished by sending a custom header like "X-Create-On-Behalf-Of: somerenter#example.com" with the PUT/POST creation request? Or should my schema define a field which allows for this alternative scenario.
I'm very much an amateur at this, so I'm open to any criticism of my assumptions/design, as well as any pointers for learning more about designing RESTful api's. Thanks for reading.
I think I've found a solution.
Landlords and Renters are really just subclasses of the same object, which I'll call Party (as in party to a transaction, not birthday party). So then each one has their own resource, named like /party/PARTY_ID.
It's easy to extend this to see that /party/SOME_LANDLORD/applications and /party/SOME_RENTER/applications solve my issues. It also removes my need to consider custom headers.