Update Stock_level in OCAPI - demandware

How I can update the inventory (stock_level) using (business manager API).
I use the business manager API to retrieve products. I am able to retrieve the products but I am not sure how I can set its stock (stock_level).
I have a special requirement where product quantity cannot exceed 1, so for that I need to set it in an inventory so that I can test it.
I have tried to see if I can set inventory level using product but that doesn't seem possible.
When I try to get inventory following is the error
{
"_v": "18.8",
"fault": {
"arguments": {
"method": "GET",
"path": "/data/v18_8/inventory_lists/*"
},
"type": "ClientAccessForbiddenException",
"message": "Access to resource 'GET /data/v18_8/inventory_lists/*' is not allowed for the current client."
}
}

There is actually a DATA API endpoint that can be used to update inventory. It is called the ProductInventoryRecords resource.
You can update a product inventory record with a PATCH eg:
PATCH /inventory_lists/{inventory_list_id}/product_inventory_records/{product_id}
With a ProductInventoryRecordAllocation payload as such:
{
"_resource_state" : "847f9c3c5867f641470b3046aeec31f07757991b792d722e10079926f7a289fb",
"allocation": {
"amount": 2000,
"reset_date": "2016-03-31T14:05:40.872Z"
}
}
See more about this document type here.
Please note that the best practice is to pass the _resource_state key to ensure that the record is properly updated. OCAPI checks to see if this value is the same as the current state of the record if that attribute provided.
So systems should first check the record to get the _resource_state by performing a GET on the same resource.
Edit Note that you'll need an authorization token that grants you access to the API in order to make this kind of call.

your question is not crystal clear but I will try to answer. Commerce Cloud has three distinct (OCAPI) APIs:
Shop API (provides similar access as a customer on the site)
Data API (provides similar access as a merchant using business manager)
Meta API (describes the API from a functional perspective)
To get availability of a product in the inventory use below call: {{shop_url}}/products/701644676568M/availability and look at ATS in the response.
To set the stocklevel go into to business manager or use business manager import utility. There is no out-of-the-box API to update the stocklevel.

Related

How to make REST calls to Tableau

I need to make REST requests to Tableau to upload and download data sources and other requests.
In the documentation mentioned here, it says that to make a REST request you need.
Server Name
SiteID
Workspace/Group ID
Where can I get these 3 things? I am new thus not familiar with the tableau platform.
Below is my Tableau Dashboard:
I see you've figured this out based on some of your other questions but here is the answer for anyone else searching.
Server name = your server's ip address or if using Tableau Online, the first portion of your url when you login.
10ay.online.tableau.com for the GET call of
https://10ay.online.tableau.com/api/3.12/sites/site-id/projects/project-id
Site ID can be returned using a POST in your API authentication call. Using the server name above the POST call would look like this https://10ay.online.tableau.com/api/3.4/auth/signin You will need to add some info to the POST body that will look like this.
{
"credentials": {
"personalAccessTokenName": "YOURTOKENNAME",
"personalAccessTokenSecret": "YOURTOKENSECRET",
"site": {
"contentUrl": "YOURSITE"
}
}
}
You don't necessarily need the group-id unless you are returning group specific info like user/group relationships. Use this in a GET call to return your group IDs by name. https://10ay.online.tableau.com/api/3.12/sites/site-id/groups

WSO2IS GET tenant by domain response does not contain the tenant id

Running WSO2IS v5.11.0. After creating a tenant with domain "example.com" using the addTenant endpoint, I execute the following REST call to retrieve it
GET https://host:port/t/carbon.super/api/server/v1/tenants/domain/example.com
Contrary to what is documented in the docs, the response does not contain the tenant's id. Here is the response:
{
"domain": "example.com",
"owners": [
{
"username": "test#example.com"
}
],
"createdDate": "2021-02-04T14:43:53.598Z",
"lifecycleStatus": {
"activated": true
}
}
Why is the id not included in the response? Am I doing something wrong or is this a bug?
Seems it is a bug in IS-5.11.0. If you try the latest milestone release 5.12.0-m9 you can retrieve the tenant id in your request.
The fix https://github.com/wso2/carbon-kernel/pull/2869 should have resolved that issue in the recent milestone versions. So you can patch this into 5.11.0 and use.
In IS-5.11.0,
If you create a tenant using POST request and retrieve the tenant by its domain GET https://host:port/api/server/v1/tenants/domain/example.com the tenant UUID will not return.
If you follow the following steps:
create a tenant using POST request
Find the Location header in the response header and get the tenant UUID
Get the tenant by GET /tenants/{tenant-id}
Next get the tenant by domain GET https://host:port/api/server/v1/tenants/domain/example.com - now you will get the tenant UUID (tenant object may be cached with its unique id due to the request in 3rd step)
So it's not an API level issue. Above mentioned carbon-kernel fix should have fixed the core level issue.

Is it considered RESTful to do additional things in POST api apart from creating a resource?

We have customer registration API that accepts name, email and mobile and generates customerId i.e.:
{
"name": "john",
"email": "john#gmail.com",
"mobile": "+134325325"
}
We create customer record for this API hit. The customer can be created from several clients and forms. We have got a new requirement that if we get this "customer creation" record from particular form, we need to send this information (name,email,mobile)+(customerId) to some third party API as well.
I believe as per resful pratise this API should only create "customer" and not do such extra things which would only be valid for certain clients/forms.
Which is the best alternative in this case:
Create new API for this new requirement: This new API would first create customer and then send it to third party API. This fulfils our requirement here but customer creation logic is now at two APIs.
Use existing "customer registration API" by adding a new flag: We would set this flag from these forms where we have this new requirement to send data to the third party as well. We would first create customer and if flag is set, we would send this data to the third party APIs as well. But is this approach RESTful?
From these forms where we need to send data to third party API, first send request to "customer registration API" and get customerId back and then send these details to third party API: This would be slow as we will have to wait for customerId on the client side.
POST is often used as a catch-all for actions that don't fit into a proper REST API otherwise. Bulk create, update or delete, merging records, logging in, copy, etc, are all common examples. But anything else you need to do that doesn't correspond to PUT, GET or DELETE can generally be overloaded with POST. Just make sure you use a distinct URL for each use of POST.
I.e. POST /foo should create a foo, and POST /bulk_delete should delete several fooa, based on query or form parameters.
I don't feel like separate resource would fit here. Let's imagine we are discussing not API endpoints design but simple class method createCustomer. Exposing a new endpoint is the same as creating a new overload method createCustomerSpecific. This is RPC-style - the number of methods will keep growing.
What REST as a style is suggesting is to use the same method, but encapsulate all the data required to create resource in the input object.
For me your case should be driven by something like repository factory: your application logics knows what repository to call - simple CustomerRepository or CustomerWithNotificationRepository.
I hope that the owner of this question may not need an answer for this. But here are my thoughts.
My assumptions are given below,
You have CustomerService class which contains the methods to perform CRUD operations with Customer Data.
You have an endpoint /api/customers(Method: POST) which will call the CustomerService.create() method to create a customer detail in DB.
With your second approach(Slight modification):
I prefer not to create an another endpoint since we are not doing anything differently apart from calling the 3rd party API. Hence the request JSON would be modified as like below to hold the additional data from client side.
{
"clientData": {
"notify": "true"
},
"customer": {
"name": "john",
"email": "john#gmail.com",
"mobile": "+134325325"
}
}
Post creation of the customer, We have to check whether the notify field is true or not. If its, then the 3rd party API would be called with the customer details for additional processing.

REST: How to update a row and create zero or more of other resource on same request?

I'll try to make this as simple as possible, it may be sort of dumb question.
I'm rewriting an 7 years old web application (help desk software). It is required to make it a REST API to be consumed by different clients web browser and mobile app. Also required to keep the business logic as close as possible to the original which for now have been working well.
The current struggle about REST:
What I need is to update the a resource lets say /tickets/47321
If the status_id of the this resource is changed a record of this change need to be saved, both in the same DB transaction because it need to be all-or-nothing. this is how the original application worked and we would like to keep this behavior.
So question is:
Can I PUT to tickets/47321 the whole resource or partial state representation to update the resource residing in server and create the new record of the history change (if status_id is different) and return them both back to client as JSON:
{
ticket: {}, // new ticket state
history: {} // the new created record of history change
}
This way the client can update the ticket and add the history to a list of history changes if there is any being return?
Technically, yes, you can do this. However, it might not be as straightforward as simply returning 2 objects, side by side; looking at the Richardson Maturity Model (Level 1), one would expect to receive the same type of resource after
calling (PUT) an api endpoint.
That being said, you could either embed the additional resource (append a history change to a ticket, following the Hypertext Application Language (HAL) proposed draft specification), or better yet (if you're aiming towards REST level 3), provide a link relationship, in conformity with the "Target IRI" defined in Web Linking specification (RFC 5988) from the ticket:
/api:history?ticketId=47321 would return all the history records belonging to that ticket, paged and sorted by created date, for example (and you can just select the latest)
/api:history?id=123 you would do some work on the server to ensure this points straight to the latest history record (related to that ticket id)
Regarding the partial update, looking at the RFC 6902 (which defines the Patch standard), from the client's perspective the API could be called like
PATCH /ticket/47321
[
{ "op": "replace", "path": "/author", "value": "David"},
{ "op": "replace", "path": "/statusId", "value": "1"}
]
More examples can be found here.

Update/create hierarchical resources REST [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am working on an REST API and I am trying to understand how to deal with hierarchical resources.
Background
Let's start with a simple example. In my API I have Users, User profiles and Reviews.
Users must have a User Profile associated (a User Profile corresponds to only one User)
Users might have a Review associated (a Review corresponds to only one User)
User's resource representation should be:
User: {
"u1": "u1value", // User's attributes
"u2": "u2value",
...
"links": [{
"rel": "profile",
"href": "http://..." // URI of the profile resource
}, {
"rel": "review",
"href": "http://..." // URI of the review resource
}]
}
User profile resource representation should be:
UserProfile: {
"p1": "p1value", // Profile attributes
"p2": "p2value",
...
"links": [{
"rel": "owner",
"href": "http://..." // URI of the user resource
}]
}
Review resource representation should be:
Review: {
"r1": "r1value", // Review attributes
"r2": "r2value",
...
"links": [{
"rel": "owner",
"href": "http://..." // URI of the user resource
}]
}
Resources URIs could be:
http://api.example.com/users/{userid}: access to the user resource
http://api.example.com/users/{userid}/profile: access to the user's profile resource
http://api.example.com/users/{userid}/review: access to the user's review resource
Resource creation: what's the correct way to create a user?
Now I want to create a new user:
POST http://api.example.com/users {"u1": "bar", "u2": "foo"} and I get back the new userid = 42
POST http://api.example.com/users/42/profile {"p1": "baz", "p2": "asd"}
PUT http://api.example.com/users {"u1": "bar", "u2": "foo", links: [{"rel": "profile", "href": "http://api.example.com/users/42/profile"]}
My concerns:
What if something breaks between 1 and 2 or 2 and 3?
In 3), should the server update automagically the links in the http://api.example.com/users/42/profile, to point to the correct owner?
Updating link fields is the proper manner to create relationships? Or should I skip step 3) and let the system guess the relationships according to URI conventions? (I read on several books that URI should be considered as opaque.)
Your concerns are well-placed and your list of issues is correct. If I may suggest, your approach looks very much like you are using a relational DB approach and are doing an INSERT, retrieving the PK from a sequence which you use for the next INSERT, and so on.
Let the server maintain referential integrity
As an observation, even if following your original scheme, omit step 3 entirely. The URI in links that is visible when you retrieve your user document should be generated by the server based on the existence of the profile record.
For example, if using a relational backend, you SELECT from USERS to get the user record. Next, you SELECT from PROFILES. If there is a record, then you modify the return datastructure to include the reference.
POST entire documents
A common way to resolve the other issues that you bring up is to allow posting of an entire document to the user URL (like NoSQL databases such as MongoDB). Here the document is the user and the profile:
{
"u1": "bar",
"u2": "foo",
"profile": {
"p1": "baz",
"p2": "asd"
}
}
In this approach, your end-point on the server receives a nested structure (document) and performs the INSERT into USERS, retrieves the PK, then performs the INSERT into PROFILES using this PK. Doing this on the server side resolves several concerns:
The transaction can be atomic
There is only one network exchange between client and server
The server does the heavy lifting and can validate the entire transaction (eg the user is not created if the profile is not valid)
No need for step 3.
Note that you this approach is in addition to the APIs you have detailed above - you still want to be able to directly access a user's profile.
GET - client can specify fields
It is interesting to compare with APIs from well-established companies. Take LinkedIn for example. In their developer API the default GET for a user returns simply the user's name, headline and URI.
However, if the request specifies additional fields, you can get the nested data, eg the second example in http://developer.linkedin.com/documents/understanding-field-selectors returns the user's name and a list company names for the positions they have held. You could implement a similar scheme for Profiles and Reviews.
PATCH for updating document properties
With inserting and querying out of the way, it might be worth considering how to update (PATCH) data. Overwriting a field is obvious, so you could, for example PATCH to http://api.example.com/users/42 the following:
{
"u1": null,
"u2": "new-foo",
"profile": { "p1": "new-baz"}
}
Which would unset u1, set u2 to new-foo and update the profile's p1 to new-baz. Note that if a field is missing (p2), then the field is not modified. PATCH is preferable to the older PUT as explained in this answer.
If you only need to update the profile, PATCH the new profile record directly to http://api.example.com/users/42/profile
DELETE should cascade
Lastly, deleting can be done with the DELETE method pointing to the resource you want to delete - be it User, Profile or Review. Implement a cascading delete so that deleting a User deletes his/her Profile and Reviews.
You should stick to HATEOAS, and dereference the URLs you get on your responses:
For ease of access, lets say User.profile contains the href of the link with rel == profile.
Create the User
With the POST you described... but it should not return an id, but a user, complete with it's links.
User: {
"u1": "bar", // User's attributes
"u2": "foo",
...
"profile": "http://api.example.com/users/42/profile",
"links": [{
"rel": "profile",
"href": "http://api.example.com/users/42/profile"
},
...
]
}
At this point the profile resource at User.profile (could be http://api.example.com/users/42/profile, or whatever location you migrate to in the future) is be whatever a default profile should be, e.g. an empty document or with just the owner link filled.
Update the Profile
profile = GET User.profile
profile.p1 = "baz"
profile.p2 = "asd"
PUT profile to the same url you just dereferenced
By dereferencing hrefs on your documents instead of constructing urls with id's you get from responses, you client will not have to change when the API changes. Like when
- profiles are moved to http://profiles.cdn.example.com/
- profiles get a p3 value
"Old" API clients will keep working without having to change any code.
Actually from successful step (1) you should get HTTP code 201 Created and an address (URL) to the newly created resource, not just the ID number. If step (2) fails your REST API should indicate whether the problem is with the client such as badly formed document (issue code 4xx) or server (5xx). For example if in the meantime resource 42 was deleted, code 404 Not Found should be returned.
Therein lies the problem with stateless REST APIs - they cannot support transactions composed of more than one request. For this to be possible you would have to maintain a session (state) on the server.
By the way, the URL in step (3) in your example suggest that you are substituting all users and probably should read http://api.example.com/users/42.
You have a choice between submitting complete user+profile document at once to be split into two database records in one atomic transaction, or to allow persistence of partial user data i.e. user without a profile.
The choice depends on the context. For example it may be perfectly fine that a user does not have a profile (so it can be provided by the user). Conversely having a profile record, which does not belong to any user is probably not acceptable. Discussion about enforcing this logic goes beyond the scope of your question and will vary by the type of persistent store (database) you choose. Relational databases enforce this using foreign keys.
I believe your calls should be like this
1) Create a user
POST http://api.example.com/users + params in payload
If it returns HTTP 201 + user id, then you can go on and create the profile. Else you treat the exception the way you want. You should wait for the first call to get back before starting the creation of the profile.
2) Create a profile associated to a user 42 (if the user creation was ok)
POST http://api.example.com/users/42/profile + params in payload
returns HTTP 201 + profile id
Your backend will be responsible for updating your user object and the profile object (and your database) so that users 42 will be linked to the new profile. If the backend cannot link the object you can send back a 500 error explaining what happened.
So in my opinion I would skip step 3.
Now I understand that your point is about the fact that a user MUST have a profile
I see 2 solutions
1) you could create an empty associated profile when creating your user. Then by querying the user you can get the profile id and modify it with a PUT (I really do not like this solution because when you are asking your api to create a user it should only create a user and nothing else but as in fact a profile is mandatory it not as ugly as it seems).
2) you could have a property in you user saying if the user is correct or not (meaning he has an associated profile). At the end of the creation process if your user 42 is not correct you can delete it or retry the profile creation ... Then you could query only correct users with something like /users?isCorrect=true
3) Let the client treat the fact that a user as no profile -> show a popup to ask for creation of the profile ...
Have a look to this document for REST API best practices
Maybe you could also have a look to HAL which tries to deal with relationship between objects.
And last but not least you could follow api-craft google group you might find interesting topics related to your issue there.