Can restful POST api send back two different resources in the API response based on request body parameter? - rest

We have a website to connect buyer and seller of goods.
We are designing POST API to capture interest of buyers on any seller product. The API Uri and request body looks like:
/api/lead/
{
"name":"xyz",
"mobile": "00984343",
"stockid":4
}
The API is POST since we will save this information in database.
Currently, if "stockid" is stock belonging to our premium customer, the API sends back seller details in API response body:
{
"sellername":"abc",
"sellermobile":"75654647",
"selleraddress": "faje street, curl"
}
If "stockid" is stock belonging to our normal customer, the API sends back complete details of that product in API response body (and DO NOT send back seller details)
{
"description": "good 2nd hand mobile",
"purchasedate": "24 july,2017",
"purchaseprice": "10000"
}
The same POST API is sending back 2 different types of resources (one is seller details, other is stock details) based on the stock id.
Is it restful to design API this way i.e. POST API sending back multiple types of responses based on some request body parameter?

This practice looks questionable. Personally I would not do that.
Suggestion 1: return details of product for normal customer, and details of product plus seller details for premium one, as form of enrichment of response. With that both responses are mostly consistent and you still have functionality you want.
EDIT: added more suggestions I thought of.
Suggestion 2: since those responses are basically different, maybe they should be returned by different resources. In that case, don't return data during POST, just use id to make calls to something like api/seller/{stockid} and api/product/{stockid} which would return responses or No content if id is invalid for specific resource. Downside, you need to make many calls and it complicates architecture.
Suggestion 3: To avoid totally different response objects, which is confusing and makes harder for the client to map them, use some wrapper object that provides some "type" property and your object inside. Something like :
{
"type" : "premium",
"data" : {
"sellername":"abc",
"sellermobile":"75654647",
"selleraddress": "faje street, curl"
}
}
Not perfect, but in my opinion better than two totally different responses.

Related

WooCommerce fulfillment api

I am making the order management system and try to integrate woocommerce api.
I read the document, found it quite different with the other ecommerce api.
When we need to pull order from the Woocommerce, use the /wp-json/wc/v3/orders api.
But when I done the order fulfillment and try to imform the shipment(advanced shipping notice), like send the tracking number correspones the order, which api should I use?
Thank you very much.
To update an existing order in WooCommerce you add the order id to the url like this /wp-json/wc/v3/orders/<id> and the request needs to be an PUT.
To store tracking url I would suggest you save it as a meta_field on the order. You can then easily access it in WooCommerce and display it where you want. Request can look like this:
{
"meta_data": [
{
"key": "_tracking_number",
"value": "XXXXXXXXXXXXX"
}
]
}
You can read more about it here https://woocommerce.github.io/woocommerce-rest-api-docs/#update-an-order

Differentiate messages within same status code from web api

I am developing a web API which will return Forbidden http status for multiple reasons-
User is blocked.
IP is blocked.
Request limit exceeded.
User is unverified.
I am returning response in following way-
return Content(HttpStatusCode.Forbidden, message); //message : "Limit reached" etc.
Now, I need to handle these reasons differently at client. Should I identify the reason from returned message? This message is to be displayed to user and might change in future.
What is the best practice for this?
What is the best practice for this?
Rather than trying to invent a schema of your own, you should probably look for something standardized, like Problem Details for HTTP APIs.
Problem Details describes a human readable "title" and "detail" field, and a "type" that is a link to human readable documentation.
Consumers MUST use the "type" string as the primary identifier for the problem type; the "title" string is advisory and included only for users who are not aware of the semantics of the URI and do not have the ability to discover them (e.g., offline log analysis). Consumers SHOULD NOT automatically dereference the type URI.
Consumers SHOULD NOT parse the "detail" member for information; extensions are more suitable and less error-prone ways to obtain such information.
Your error message should be descriptive for your client. Ideally you need to include the following information:
developers message (technical description - "cache is out-of-date", "service A is unavailable")
human-readable message (business description - "this time is booked already", "company A is closed and cannot be modified")
hint how to solve ("refresh your cache", "try again in 5 minutes", "request permission A from administrator")
href to your online documentation
Header like "error_code: 100". A custom code should also be described in the documentation. This one you may rely on in your client's code and handle appropriately
Also what do you mean by:
User is unverified.
In case user is not Authenticated (api doesn't know who is he), api is supposed to return 401 http status code. If user lacks some permission and therefore cannot modify the resource than 403 is totally fine. However it would be great to describe which permission exactly is missing

Facebook pixel events call from server

I have absolutelly the same question as dan here - Facebook conversion pixel with "server to server" option . There was written, that there was no way, but it was 2013, so I hope something changed.
So, is there any way to call facebook pixel events (e.g. CompleteRegistration) from server side now?
I can describe situation in more details. Imagine, that user visits our site, where fb pixel tracks 'PageView' of course. When user passes form and sends his phone number, we call 'Lead' event. But then we need to track one more event, when our manager successfully confirmes this user! Of course, it happens on other computer and so on, so there is no idea, how to "connect" to base user.
I've seen a lot of documentation departments like this, but I can't fully understand even if it's possible or not.
Logically, we need to generate specific id for user (or it can be phone number really), when 'Lead' event is called. Then, we should use this id to 'CompleteRegistration' for that user. But I can't understand, how to do it technically.
It would be gratefull, if somebody could explain it.
P.S. As I understand, it is fully available in API for mobile apps. Is it ok idea to use it for our situation, if there is no other solution?
Use Offline Conversions to record events that happen after a user has left your website. Logging these conversions, technically, is very easy. Setting everything up takes a little effort
tldr; check the code below
Follow setup steps in the FB docs (Setup steps 1-5) which are:
Setup facebook Business Manager account
Add a new app to Business Manager account
Create an Ad account, if you don't already have one
Create a System User for the ad account
After the setup, follow Upload Event Data steps on the same page, steps 1-3 to create an offline event set and associate it with your ad. These can be carried out in the Graph API Explorer by following the links in the examples. These can be done programmatically, but is out of the scope of making the event calls from the server for one campaign.
Once you have created the event set, then you can upload your CompleteRegistration events!
You will need to make a multipart form data request to FB, the data key will be an array of your conversion events. As #Cbroe mentioned, you must hash your match keys (the data you have available about your user to match them with a FB user) before sending to FB. The more match keys you are able to provide, the better chance at matching your user. So if you can get their email and phone at the same time, you're much more likely to match your user.
Here's an example of the call to FB using node.js:
var request = require('request')
// The access token you generated for your system user
var access_token = 'your_access_token'
// The ID of the conversion set you created
var conversionId = 'your_conversion_set_id'
var options = {
url: 'https://graph.facebook.com/v2.12/' + conversionId + '/events',
formData: {
access_token: access_token,
upload_tag: 'registrations', //optional
data: [{
match_keys: {
"phone": ["<HASH>", "<HASH>"]
},
currency: "USD",
event_name: "CompleteRegistration",
event_time: 1456870902,
custom_data: { // optional
event_source: "manager approved"
},
}]
}
}
request(options, function(err, result) {
// error handle and check for success
})
Offline Conversion Docs
Facebook has now a Server-Side API: https://developers.facebook.com/docs/marketing-api/server-side-api/get-started
Implementing this is similar to implementing the offline events outlined in the accepted answer.
Keep in mind that it will always be cumbersome to track and connect events from the browser and from your server. You need to share a unique user id between the browser and server, so that Facebook (or any other analytics provider) will know that the event belongs to the same user.
Tools like mixpanel.com and amplitude.com may be more tailored to your needs, but will get very expensive once you move out of the free tier (100+ EUR at mixpanel, 1000+ EUR at Amplitude, monthly). Those tools are tailored towards company success, whereas Facebook is tailored towards selling and measuring Facebook ads.

Rest convention: Should api send details api url for listings or clients hard code them?

We have listing and details page for mobile, desktop, android and ios?
We have two apis- one for listing and other for details of those listings. So one api is assosiated with other.
listing api looks like:
/api/books/?price=100-300
details api looks like:
/api/book/{bookId}
listing api in response sends back details api link for each listing:
For example:
Request:
/api/books/?price=100-300
will have Response:
{
"books":[
{
"id": 1,
"price": 120,
"pages": 400,
"detailsUrl": "/api/book/{bookId}"
}
]
}
The problem is, should I send detailsUrl with each listing or let all the clients create this? Since they have bookId, they can create it.
What is considered to be best practise considering the url params in details api url may get added in future, api may be versioned and all other possibilities for widely used apis?
I'd put my money on creating the link.
There is a perfect explanation why putting id is not enough
DO NOT include just an entity's ID (such as 12) in a response, because
that way you're forcing clients to put together resource URIs
themselves. In order to do that, they would need to have prior
knowledge of what URIs there are, and you're losing control over the
URI space on the server side.
I recommend to read the entire, linked text (approved answer), it's very detailed and got nice resources. As the author mentioned, there is a popular convention how to make connections between resources - HAL. Consider this instead of detailsUrl.
Even if a link to the resource is obvious right now and you decided to put id alone, in other resources after some time it won't be so simple and you will be forced to specify full URL. Then your API won't be consistent. Experience has taught me it's always easier and better for maintenance to send back full link.

Restful API: Is it meaningful to send PUT without enclosed entity?

Consider the following scenario:
There are two existing entity: shopping card #1 and item #1. I want to add item #1 to shopping card #1. There are two possible ways to design a Restful api:
1:
Without body:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Host: myshoppingsite.com
2: With body (having enclosed-entity):
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Host: myshoppingsite.com
{itemId: "1"}
Actually, I cannot decide which one is better and is more meaningful in terms of restfulness. Any idea?
(Note: I believe the http method should be PUT because of idempotency, but this is not my question here.)
PS: The problem I have with the first design is that there is no such enclosed entity in the request. Linguistically put is a transitive verb, so I expect somebody puts something somewhere. I think the same story somehow is in the HTTP world.
PUT is a HTTP verb that is supposed to create or replace the target URI, so this makes your first option immediately wrong. This request should replace all the items in your shopping cart:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Since you want to add something to your shopping cart, this is not an option. This leaves effectively two options. First: the common one:
POST http://myshoppingsite.com/api/shoppingcards/1/items/
POST can mean many things, but in the context of REST services it's often used to append something to a collection. However, you mention that you want idempotence. You have two options here, first you can still use POST and within the context of your API guarantee that the request will be idempotent. Using POST does not mean that it's per definition non-idempotent, it just means that the HTTP spec alone does not guarantee it. That does not prevent you from making the request idempotent.
The other option is indeed PUT:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Your have a concern with that though, because in the context of your API you say that the request body would end up empty.
The reason for this is that you attach special to the last /1 in the url, and I think this what's wrong. If you want to follow REST best practices, then urls should not have any special meaning.
I think a saner way to do this, if you insist on using PUT is to get rid of the notion of "an id". That concept only exists in your database and should not make its way to the API.
Instead, I imagine that your service has a list of products such as this one:
http://myshoppingsite.com/products/1
To add a product to a shopping cart using PUT, this request might look something like this:
PUT http://myshoppingsite/api/shoppingcards/1/items/[completely-arbitrary-string-or-perhaps-a-uuid]
Content-Type: application/json
{
"product" : "http://myshoppingsite.com/products/1",
"quantity" : 5
}
Personally, I would just use POST though.
Q: there should be some information about the product you are addisng, no? Yes and that information is part of Uril. Why is it bad?
I'm not saying it's bad, I'm saying it's not RESTful. Pick up any book about REST and you will see this confirmed. This might also be a good place to start reading more about what REST is:
http://martinfowler.com/articles/richardsonMaturityModel.html
I would personally say that very little people build true RESTful services. This is why I also want to specifically point out that I don't want to say this is bad or good for your specific API, it's simply not RESTful.
What if I don't care about these principles and want to keep my special-meaning url scheme?
Well that's a fair point, but then we've gone beyond the original question here. If you want to design an API where the last bit of the url is actually the 'representation' of the item in your shopping cart, then yes I agree that having it also in the body is redundant.
In that situation I'd say, keep the request body empty. Just don't call it REST I guess.