JSON.md 10.1 KB
Newer Older
Nigel Kukard's avatar
Nigel Kukard committed
1
2
# AWIT JSON Format Standard

3

4

5
6
7
8
# HTTP Methods

Make sure during implementation you read [RFC7231](https://tools.ietf.org/html/rfc7231).

9

10
## POST
11
12
The POST method is utilized to **create** new resources. POST to a parent resource must associate the new resource with the parent,
assigning an ID (new resource URI), etc.
13

14
15
On successful creation, return HTTP status 201, returning a Location header with a link to the newly-created resource with the 201
HTTP status.
16

17
### Return Codes
18
19
20
21
22
* 201 (Created)
  * 'Location' header with link to /record/{id} containing new resource ID.
* 404 (Not Found)
* 409 (Conflict)
  * If resource already exists.
23

24
25
26
### Examples
* POST http://www.example.com/customers
* POST http://www.example.com/customers/12345/orders
27

28

29
## GET
30
31
The GET method is used to **read** a resource. In a non-error path, GET returns a HTTP status of 200 (OK). In an error case,
it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).
32
33

### Return Codes
34
35
36
37
38
39
40
* 200 (OK)
  * List of records. Use pagination, sorting and filtering to navigate big lists.
* 200 (OK)
  * Single record.
* 404 (Not Found)
  * If ID not found or invalid.

41
42
43
44
45
### Examples
* GET http://www.example.com/customers/12345
* GET http://www.example.com/customers/12345/orders
* GET http://www.example.com/buckets/sample

46

47
## PUT
48
49
The PUT method is utilized for **replace**, PUT-ing to a known resource URI with the request body containing the replacement
resource data.
50

51
On successful replacement, return 200 (or 204 if no changes were made).
52
53

### Return Codes
54
55
* 200 (OK)
* 204 (No Content)
56
  * If no changes were made.
57
58
59
* 404 (Not Found)
  * If ID not found or invalid.

60
61
62
63
### Examples
* PUT http://www.example.com/customers/12345
* PUT http://www.example.com/customers/12345/orders/98765

64

65
## PATCH
66
67
The PATCH method is used for **modify**. The PATCH request only needs to contain the changes to the resource, not the complete
resource.
68

69
On successful modification, return 200 (or 204 if no changes were made).
70
71

### Return Codes
72
73
* 200 (OK)
* 204 (No Content)
74
  * If no changes were made.
75
76
77
* 404 (Not Found)
  * If ID not found or invalid.

78
79
80
81
82
### Examples
* PATCH http://www.example.com/customers/12345
* PATCH http://www.example.com/customers/12345/orders/98765


83
## DELETE
84
DELETE is used to **delete** a resource identified by a URI.
85

86
On successful deletion, return HTTP status 200 (OK).
87
88

### Return Codes
89
90
91
92
* 200 (OK)
* 404 (Not Found)
  * If ID not found or invalid.

93
94
95
96
### Examples
* DELETE http://www.example.com/customers/12345
* DELETE http://www.example.com/customers/12345/orders

97

98
## OPTIONS
99
100
The OPTIONS method is used for introspection. This allows for both introspection of collection methods available and introspection
of record information.
101
102
103
104
105
106
107
108
109
110
111

Using the OPTIONS method on the root path of the URI followed by a \* should provide a list of collections available.

Using the OPTIONS method on a collection :record_id path should provide information on the record structure.

The 204 error code should be returned if OPTIONS is not implemented for the requested resource.

### Return Codes
* 404 (Not Found)
* 200 (OK)
* 204 (No Content)
112
  * If OPTIONS is not implemented for this resource.
113
114
115
116
117
118
119
120

### Examples
* OPTIONS http://www.example.com/\*
* OPTIONS http://www.example.com/customers
* OPTIONS http://www.example.com/customers/:record_id


## PROPFIND
121
122
The PROPFIND method is used for introspection. This will allow the return of properties for a collection as a whole. It can also
be used to determine properties of arbitrary resources.
123
124
125
126
127
128
129
130
131

Using the PROPFIND method on the root path of the URI should return information on the API.

The 204 error code should be returned if OPTIONS is not implemented for the requested resource.

### Return Codes
* 404 (Not Found)
* 200 (OK)
* 204 (No Content)
132
  * If PROPFIND is not implemented for this resource.
133
134
135
136
137
138

### Examples
* PROPFIND http://www.example.com/customers



139
# Data Format
Nigel Kukard's avatar
Nigel Kukard committed
140

141

Nigel Kukard's avatar
Nigel Kukard committed
142
143
144
145
146
147
148
149
150
151
## The 'status' field

The purpose of this field is to signify the status of the action just performed.

|  Value  | Description | Required | Optional |
| ------ | ----------- | ------------- | ------------- |
|success|The action succeeded, the 'data' key may contain a additional information||message,data|
|fail|There was a problem with the data submitted, the 'data' field must contain additional information|message||
|error|An error occurred in processing the request, the 'data' field must contain additional information in a 'message' field and may contain an additional 'data:code' and 'data:errors' (array) fields|message|data:code,data:errors|

152
### Example success
Nigel Kukard's avatar
Nigel Kukard committed
153
154

For a brief status message one could use...
155
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
156
157
158
159
160
161
{
  status: "success"
}
```

For a full status message one could use...
162
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
163
164
165
166
167
168
169
{
  status: "success",
  message: "Record 17 deleted"
}
```

For a successful status which returns records...
170
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
171
172
173
174
175
176
177
178
179
180
181
182
{
  status: "success",
  data: {
    records: [
      { id: 1, subject: "hi" },
      { id: 2, subject: "bye" }
    ]
  }
}
```

For a successful status which returns a single result...
183
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
184
185
186
187
188
189
190
191
192
193
194
{
  status: "success",
  data: {
    result: {
      username: 1,
      firstname: 2
    }
  }
}
```

195
### Example for a fail
Nigel Kukard's avatar
Nigel Kukard committed
196
197

Failures must have a mesasge field...
198
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
199
200
201
202
203
204
{
  status: "fail",
  message: "System failure, please try again later"
}
```

205
Or it can be verbose...
206
```jsonnet
207
208
209
210
211
212
213
214
215
216
217
218
219
{
  status: "fail",
  message: "System failure, please try again later",
  data: {
    code: 17,
    errors: [
      "Contacting remote server failed",
      "Server: xyz, Port: 123, Error: Connection reset by peer"
    ]
  }
}
```

220
### Example for a error
Nigel Kukard's avatar
Nigel Kukard committed
221
222

An error can be brief...
223
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
224
{
225
  status: "error",
Nigel Kukard's avatar
Nigel Kukard committed
226
227
228
229
230
  message: "The contents of the 'subject' field is invalid"
}
```

Or it can be verbose...
231
```jsonnet
Nigel Kukard's avatar
Nigel Kukard committed
232
{
233
  status: "error",
Nigel Kukard's avatar
Nigel Kukard committed
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  message: "Input failed validation",
  data: {
    code: 17,
    errors: [
      "Field 'title' is invalid",
      "Field 'subject' is blank"
    ]
  }
}
```


## The 'message' key

The purpose of this key is to give a quick status message as to the result of the action. This is optional for success and mandatory for failurs and errors.

The format of this keys data is plain text.

252

Nigel Kukard's avatar
Nigel Kukard committed
253
254
255
## The 'data' field

This field contains result data. Either a 'result' key or a 'records' key.
Nigel Kukard's avatar
Nigel Kukard committed
256
257

See the 'status' field definition above for examples.
258

259
260


261
262
# Examples

263
## Introspection examples
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

### API information using /

Using the PROPFIND method request to http://www.example.com may look like this...
```jsonnet
{
  "status": "success",
  "data": {
    "title": "Issue Tracker App",
    "description": "This is a sample server for issue tracking.",
    "termsOfService": "http://www.example.com/terms",
    "contact": {
      "name": "API Support",
      "url": "http://www.example.com/contact",
      "email": "support@example.com"
    },
    "version": "0.0.1"
  }
}
```

### Collection list using path /*

An OPTIONS method request to http://www.example.com/\* may look like this...
```jsonnet
{
  "status": "success",
  "data": {
    "result": {
      "collections": [
        "/issues"
      ]
    }
  }
}
```

### Collection information

A OPTIONS method request to http://www.example.com/issues may look like this...
```jsonnet
{
  "POST": {
    "description": "Create an issue",
    "path": "/issues",
    "parameters": {
      "title": {
        "type": "string"
        "description": "Issue title.",
        "required": true
      },
      "body": {
        "type": "string",
        "description": "Issue body.",
      },
      "assignee": {
        "type": "string",
        "description" "Login for the user that this issue should be assigned to."
      },
      "milestone": {
        "type": "number",
        "description": "Milestone to associate this issue with."
      },
      "labels": {
        "type": "array/string"
        "description": "Labels to associate with this issue."
      }
    },
    "returns": {
      "status": {
        "type": "status",
        "description": "Result of request"
      },
      "data": {
        "type": "hash",
        "description": "Data hash containing record details, returned only on success",
        "children": {
          "record_id": {
            "type": "integer",
            "description": "ID of the created record"
          }
        }
      }
    }
    "example": {
      "title": "Found a bug",
      "body": "I'm having a problem with this.",
      "assignee": "octocat",
      "milestone": 1,
      "labels": [
        "Label1",
        "Label2"
      ]
    }
  }
  "DELETE": {
    "description": "Delete an item",
    "path": "/issues/:record_id",
    "parameters": {
      "record_id": {
        "type": "integer"
        "description": "Record ID",
        "required": true
      },
    },
    "returns": {
      "status": {
        "type": "status",
        "description": "Result of request"
      },
    }
  }
  "PATCH": {
    "description": "Change an item",
    "path": "/issues/:record_id",
    "parameters": {
      "record_id": {
        "type": "integer"
        "description": "Record ID",
        "required": true
      },
    },
    "returns": {
      "status": {
        "type": "status",
        "description": "Result of request"
      },
    }
  }
  "PUT": {
    "description": "Replace an item",
    "path": "/issues/:record_id",
    "parameters": {
      "record_id": {
        "type": "integer"
        "description": "Record ID",
        "required": true
      },
    },
    "returns": {
      "status": {
        "type": "status",
        "description": "Result of request"
      },
    }
  },
  "OPTIONS": {
    "description": "Record information",
    "path": "/issues/:record_id",
    "parmaeters": {
      ":record_id": {
        "type": "string",
        "description": "This is a string literal ':record_id'",
Nigel Kukard's avatar
Nigel Kukard committed
417
        "required": true,
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
      }
    },
    "returns": {
      "status": {
        "type": "status",
        "description": "Result of request"
      },
    }
  },
  "PROPFIND": {
    "description": "Collection information",
    "path": "/issues",
    "parameters": { },
    "returns": {
      "records": {
        "type": "integer",
        "description": "Number of items in collection",
      }
    }
  }
}
```


442
443
# Acknoledgements

444
445
446
Inspired by [RestApiTutorial.com](http://www.restapitutorial.com)

Inspired by [Swagger.io](http://swagger.io/specification)
447