Response format¶
Every API of API Maker, generated, schema, custom or system, 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, 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, snakeCase, pascalCase, paramCase… ; any other value leaves the keys as they are (see the values). |
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.