Response format¶
Every API of API Maker, generated, schema, custom, system or third party, answers with the same envelope, so one client handles all of them the same way.
The envelope¶
A successful answer
{
"success": true,
"statusCode": 200,
"data": [ { "customer_id": 1, "first_name": "Bob", "last_name": "Lin" } ],
"totalCount": 5,
"warnings": [],
"logs": [],
"meta": {}
}
dataholds the result,totalCountcomes withgetTotalCount=true,warningsandlogswhen there are some,metawith the headerx-am-meta: true. Absent keys are simply not sent.
A refused request
{
"success": false,
"statusCode": 400,
"errors": [
{ "type": "required", "field": "first_name", "message": "Please provide valid 'first_name' field with type 'string'.", "code": 400 }
],
"warnings": []
}
errorslists every problem found, each with itscode,message, and for data problems thefieldand thetypeof the rule. The HTTP status of the reply isstatusCode.
| Key | When | Meaning |
|---|---|---|
success |
always | true when the request did what it was asked, false otherwise. |
statusCode |
always | The HTTP status of the reply, repeated in the body : 200, 201 for a save, 400, 401, 403, 404 or 500. |
data |
on success, and on some failures | The result : an array for get all and the query APIs, an object for get by id, a save of one object, an update ; whatever a custom API returns. null when there is nothing. |
totalCount |
with getTotalCount=true |
The number of rows matching the filter, without skip and limit. |
errors |
on failure | One entry per problem. Data problems name the field and the type of the rule ; the message follows the language asked with x-am-internationalization. |
warnings |
when there are some | Problems which did not stop the request, in the same shape as errors : for example a deep which found no target. |
logs |
when your code logged | What g.logger printed while a custom API, a hook or an event ran, so the caller can see it. |
meta |
with x-am-meta: true |
executionTime, executionPlan (MongoDB explain), apiAccessGroups (which group granted the call) and runBy (which server, process and sandbox ran the code). |
encryptedData |
with x-am-get-encrypted-data |
The response encrypted with the transfer key of the secret, next to or instead of data. |
An error entry¶
{
"type": "min",
"field": "price_cents",
"message": "Please provide minimum '0' for 'price_cents' field.",
"code": 400,
"dataIndex": 2
}
| Key | Meaning |
|---|---|
type |
The rule which failed : required, min, max, minLength, maxLength, email, enumValidation, invalidValue (a wrong type, a thrown validatorFun, a concurrency version mismatch…), schemaKeyNotFound (a key the schema does not have), schemaNotFound, unique, virtualFieldUsedInFind. |
field |
The field concerned, with dots for nested fields. |
message |
The text, from the message templates or your own throw, translated when the caller asks for a language. |
code |
The HTTP status of this problem. The statusCode of the reply is the highest one. |
dataIndex |
For a save of several objects : the index of the object in the array. |
stack, apiCallSequence |
Present for unexpected errors of your code, to help you debug : the stack as lines, and the chain of APIs which led there. |
Status codes¶
| Code | Meaning |
|---|---|
200 |
Done. |
201 |
Created : a save through save single or multiple or master save. |
400 |
The request is wrong : validation errors, an unknown key, a bad query, a missing body. |
401 |
The token is missing, malformed or expired. Get a new one from the token API. |
403 |
The token is fine but no group of the API user grants this API, this table or this field ; or the origin of the browser is not allowed. Fix the group, do not sign the user out. |
404 |
The path does not exist : a typo in the URL or a wrong method, an instance name which is not there. Also the answer of update by id, replace by id and remove by id with throwErrorIfRecordNotFound=true when the id is unknown. |
500 |
An error of your code or of the database. The message and, for your code, the stack are in errors. |
The format of the reply¶
The body is JSON unless the request asks otherwise with headers :
| Header | Effect |
|---|---|
x-am-content-type-response |
application/json (default), text/xml, text/yaml, text/plain, text/html, application/octet-stream. The envelope is the same, only its encoding changes. |
x-am-response-case |
The case of every key : camelCase, snake_case, PascalCase, kebab-case… |
x-am-response-object-type: make_flat |
Nested objects flattened with _ between the levels : state_id_country_id_country_name. |
x-am-meta: true |
Adds meta. |
x-am-get-encrypted-data |
Adds or replaces data with encryptedData. |
x-no-compression: true |
No gzip or brotli, whatever the size (replies bigger than compressThreshold, 51200 bytes by default, are compressed otherwise). |
A custom API can also answer something other than the envelope : set g.res.contentType to a MIME type and return a string, or return a file, see Content types and the download example.
Response headers¶
| Header | Meaning |
|---|---|
x-am-data-source |
cache when the reply came from Redis, api when the API ran. |
Content-Encoding |
gzip or br when the reply was compressed. |
In your code¶
The same envelope is what g.sys.db.*, g.sys.system.* and g.sys.cache.* return when you ask for the full response with the second argument true. Without it, they return data and throw the errors.