Handling an error with multiple attributes or parameters with JSON API - api-design

JSON API specifies that multiple errors on an attribute/parameter should be listed separately. What is the best way to handle a single error that involves several parameters at once?
For example, let's say an endpoint accepts either bid or fold parameters, but not both (they are mutually exclusive). What should be the error response if both of parameters are submitted (GET /endpoint?bid=100.00&fold=muck)?
List the error twice, once for each attribute?
{
"errors": [
{
"status": "400",
"source": { "parameter": "bid" },
"detail": "Cannot accept both 'bid' and 'fold' parameters."
},
{
"status": "400",
"source": { "parameter": "fold" },
"detail": "Cannot accept both 'bid' and 'fold' parameters."
}
]
}
Combine the attributes?
{
"errors": [
{
"status": "400",
"source": { "parameter": ["bid", "fold"] },
"detail": "Cannot accept both 'bid' and 'fold' parameters."
}
]
}
Make one higher-level error for the entire request?
{
"errors": [
{
"status": "400",
"source": { "pointer": "/data" },
"detail": "Cannot accept both 'bid' and 'fold' parameters."
}
]
}
Some other way?

TL;DR version: the first one is probably right.
Neither the JSONAPI specification nor the forum details how to format errors on mutually exclusive parameters/data. It does have this:
A server MAY choose to stop processing as soon as a problem is encountered, or it MAY continue processing and encounter multiple problems. For instance, a server might process multiple attributes and then return multiple validation problems in a single response.
To rephrase your question, what you're asking is something like this: "If you include a second parameter that is forbidden when using the first parameter, is it a single error, or multiple errors?"
This suggests, in one view, that there is only one error - Cannot accept 'bid' when using 'fold' (or alternatively in the opposite direction, if you care about ordering), and that error would only point at one parameter, since you can't encounter that error until you've processed one of the parameters.
More practically, you're checking that you have both of them at once, and encounter the error not because you had one parameter and then encountered the other, but because you know you have both parameters and now have to deal with that problem. This is still a single error, pointing at two parameters (this is the premise of your question).
The JSONAPI spec for Error Objects indicates this:
parameter: a string indicating which URI query parameter caused the error.
Since you must use a string (not Array) to indicate the source of the error, and the error is in the parameters and not the request body, you have a choice of viewing this as I laid out above to call this a single error caused by only one of the parameters, or the same error equally attributed to both parameters, as you do in your first example.
Personally I prefer to view this as a single error caused by whichever parameter comes last in the query string, but your first option is probably most correct.

Plan A suffers from the fact that resurrecting the full context of error is now pushed to the caller. For example, if the caller fixed one error and the other "magically" disappeared - that could be potentially confusing.
Within Plan A, you could add meta option to point out the cross-linkage as some extra help.
Plan B in comparison feels correct as it captures the essence of the error scenario (multi-parameter) plus pins them down concisely. Naturally, you will also need to request an API enhancement, probably requesting for an array of source. For example:
"source" : [ {parameter...}, {parameter...} ]

Related

Issues while expanding URNs in versioned creatives response

We are migrating our APIs from unversioned to versioned, and having an issue while trying to get assets data from creatives endpoint.The response has reference to a post, but we are unable to use the expand URNs concept and get the inner media details of the Post URN. Is there a different approach we need to follow here?
I've read through all the migration documents and the response decoration document is also pointing to v2 endpoint and projection parameters, instead of using rest endpoint and fields parameter. Document reference.
Previous Request
GET -
https://api.linkedin.com/v2/adCreativesV2?ids[0]=181794673&projection=(results(*(variables(data(com.linkedin.ads.SponsoredVideoCreativeVariables(userGeneratedContentPost~(specificContent(com.linkedin.ugc.ShareContent(shareCommentary,media(*(media~:playableStreams(),title)))))))))))
This request gets us the media details of the creatives without making multiple calls.
Current Request
GET - https://api.linkedin.com/rest/creatives?ids=List(urn%3Ali%3AsponsoredCreative%3A181794673)&fields=(results(*(content(reference~($URN)))))
I am looking at the response I got from https://api.linkedin.com/rest/creatives?ids=List(urn%3Ali%3AsponsoredCreative%3A181794673) and trying to create the fields request. But no luck yet and getting the below error.
{
"status": 400,
"code": "ILLEGAL_ARGUMENT",
"message": "Invalid projection parameter: (results(*(content(reference~($URN)))))"
}
But when tried with projection in place of fields I got a response
{
"results": {
"urn:li:sponsoredCreative:181794673": {
"content": {
"reference": "urn:li:ugcPost:6905584391779950593",
"reference!": {
"message": "Not enough permissions to access deco: ugcPosts.BATCH_GET.20230101",
"status": 403
}
}
}
}
}
Can someone help me getting the data similar to how we got it before, without making external calls? Otherwise I think I have to be making calls to Creatives -> Posts -> Video, Image, Share etc endpoints

Always get “Cannot parse non Measurement Protocol hits”

I have a little Python program that other people use and I would like to offer opt-in telemetry such that can get an idea of the usage patterns. Google Analytics 4 with the Measurement Protocol seems to be the thing that I want to use. I have created a new property and a new data stream.
I have tried to validate the request and set it to www.google-analytics.com/debug/mp/collect?measurement_id=G-LQDLGRLGZS&api_secret=JXGZ_CyvTt29ucNi9y0DkA via post and send this JSON payload:
{
"app_instance_id": "MyAppId",
"client_id": "TestClient.xx",
"events": [
{
"name": "login",
"params": {}
}
]
}
The response that I get is this:
{
"validationMessages": [
{
"description": "Cannot parse non Measurement Protocol hits.",
"validationCode": "INTERNAL_ERROR"
}
]
}
I seem to be doing exactly what they do in the documentation or tutorials. I must be doing something wrong, but I don't know, what is missing. What do I have to do in order to successfully validate the request?
Try to remove /debug part in the URL. In the example you followed it is not present so it is not quite exactly the same.
we just came across the same issue and the solution for us was to put https:// in front of the URL. Hope this helps.

Error NGEO_ERROR_GRAPH_DISCONNECTED when calculating a route

When I calculate the route from coordinate 49.4935,0.5118 to 41.8114,2.7408 (truck + trailer 40ton) the web service returns error 400 - Bad request.
I have tested this with the example https://tcs.ext.here.com/examples/v3/fleet_telematics_api, and this explains the reason: the second waypoint is in a zone with a restriction of 7.5 ton (see image).
Is there a possibility to get this error from the webservice, so I can alert the user what the problem is?
Here example
When you make your request, you get this response:
{
"issues": [
{
"message": "Couldn't reach way point 1 (start links 907492075 -907492075 907492077 -907492077 907493126 -907493126 dest links 719515104 -719515104 ), link 907492075 might restrict access for the vehicle type, link 907492075's through traffic restriction might apply, link 907492077 might restrict access for the vehicle type, link 907492077's through traffic restriction might apply, link 907493126's through traffic restriction might apply"
},
{
"message": "Request id: bfb4932d-f159-4d3a-986e-77f6bc41b143"
}
],
"response": null,
"error_id": "bfb4932d-f159-4d3a-986e-77f6bc41b143",
"response_code": "400 Bad Request"
}
The response code is 400 Bad Request but there is also a list of messages in issues that you can use to alert the user.

How can I fix a 501 error from the clockify API?

I'm getting a 501 response from the clockify API when trying to create a Time Entry using CreateTimeEntryRequest
I've verified I can query the API and get data from it, so I'm using the correct X-Api-Key, I've resolved a few issues with bad datetime formats, but I'm still getting the error.
URL I'm posting to:
https://api.clockify.me/api/workspaces/REMOVED/timeEntries/
My POST request header looks like this:
{"x-api-key": REMOVED, "Content-Type": "application/json"}
The body of the request is (For example):
{"start": "2019-01-28T14:53:04Z", "billable": false, "description": "Test Time Entry", "projectID": null, "taskID": null, "end": "2019-01-28T15:53:04Z", "tagIds": []}
I'm getting:
{"message": "Entity not created.", "code": 501}
And the time entry is not being created.
I expect some kind of success message
It has something to do with the "End" variable. If you remove it, it'll work. This of course means the timer will be running (also you will get a 400 error if you already have a timer running), so if you want to stop it, you'll have to immediately call PUT /workspaces/{workspaceId}/timeEntries/endStarted or if you want the stop time to be at some point in the past, you'll have to update the timer with PUT /workspaces/{workspaceId}/timeEntries/{id}. However the update doesn't seem to work either (same issue). My guess is they made a change to the endpoint (perhaps renamed the "end" variable), because I'm about 75% sure I used this API within the last month or so and it worked.
Hopefully someone from Clockify will see this and give an update. I had a similar issue happen with the "me" field in the GetSummaryReportRequest object. It stopped working and removing the field fixed it.

Request reuse in Postman

Our team wants to automate our REST API testing. Right now, we have a collection of Postman requests and make them jump through hoops manually.
We could create a collection/folder for each testing scenario, but that would mean a ton of duplication. Our API is still under heavy development and I really don't want to fix the same thing at twenty places after it changes.
I would like to have each endpoint request only once in a collection and some kind of independent logic that can execute them in an arbitrary order. I know Postman doesn't support request reuse in any clean way, so I am looking for at least a hacky way how to do it.
Create a file to load into the Postman Collection Runner, with the following structure:
[{
"testSequence": ["First request name", "Second request name", "..." ],
"anyOtherData": "Whatever the request needs",
"evenMoreData": "Whatever the request needs",
"...": "..."
},{
"testSequence": ["Login", "Check newsfeed", "Send a picture", "Logout" ],
"username": "Example",
"password": "correcthorsebatterystaple",
},{
"...": "keep the structure for any other test scenario or request sequence"
}]
Put all your test sequences in that file, then make Postman check the list after each request and decide what to execute next. This can be done e. g. in a "tests block" of the whole collection:
// Use the mechanism only if there is a test scenario file
// This IF prevents the block from firing when running single requests in Postman
if (pm.iterationData.get("testSequence")) {
// Is there another request in the scenario?
var sequence = pm.globals.get("testSequence");
if ((sequence instanceof Array) && (sequence.length > 0)) {
// If so, set it as the next one
var nextRequest = sequence.shift();
pm.globals.set("testSequence", sequence);
postman.setNextRequest(nextRequest);
} else {
// Otherwise, this was the last one. Finish the execution.
postman.setNextRequest(null);
}
}
If your requests need to use different data during different runs, you can define the data in the input file and use them as variables in the request.

Resources