{
	"info": {
		"name": "Tetiva Playground",
		"description": "One host, four protocols, 20 requests. Tetiva Playground at `playground.tetiva.app` answers with what you sent, any status you ask for, as slowly as you like. No key, nothing stored, not a proxy. The two streaming gRPC calls are in the gRPC folder as grpcurl commands.",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
	},
	"item": [
		{
			"name": "REST · Echo",
			"description": "Every echo answers with the method, URL, query (as `args`), headers and body it received, plus a `request_id`. A JSON body comes back raw in `data` and parsed in `json`; forms and multipart uploads come back in `form` and `files`.",
			"item": [
				{
					"name": "Echo a GET",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/get?source=docs&page=2"
						},
						"description": "Returns your request as JSON: query parameters in `args`, headers in `headers`, your IP in `origin`."
					},
					"response": [
						{
							"name": "Echo",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/get?source=docs&page=2"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "314"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"GET\",\n  \"url\": \"https://playground.tetiva.app/get?source=docs&page=2\",\n  \"args\": {\n    \"page\": \"2\",\n    \"source\": \"docs\"\n  },\n  \"headers\": {\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\"\n  },\n  \"origin\": \"203.0.113.42\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Echo my POST body",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\"hello\":\"world\"}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/post"
						},
						"description": "Send a JSON body and get it back: raw in `data`, parsed in `json`. Bodies go up to 1 MB; forms and multipart files come back in `form` and `files`."
					},
					"response": [
						{
							"name": "Echo",
							"originalRequest": {
								"method": "POST",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"body": {
									"mode": "raw",
									"raw": "{\"hello\":\"world\"}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/post"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "397"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"POST\",\n  \"url\": \"https://playground.tetiva.app/post\",\n  \"args\": {},\n  \"headers\": {\n    \"Content-Length\": \"17\",\n    \"Content-Type\": \"application/json\",\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\"\n  },\n  \"data\": \"{\\\"hello\\\":\\\"world\\\"}\",\n  \"json\": {\n    \"hello\": \"world\"\n  },\n  \"origin\": \"203.0.113.42\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Echo a PUT",
					"request": {
						"method": "PUT",
						"header": [
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n  \"id\": 42,\n  \"name\": \"Ada Lovelace\",\n  \"role\": \"admin\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/put"
						},
						"description": "The same echo for PUT: the body comes back in `data` and `json`."
					},
					"response": [
						{
							"name": "Echo",
							"originalRequest": {
								"method": "PUT",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"body": {
									"mode": "raw",
									"raw": "{\n  \"id\": 42,\n  \"name\": \"Ada Lovelace\",\n  \"role\": \"admin\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/put"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "488"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"PUT\",\n  \"url\": \"https://playground.tetiva.app/put\",\n  \"args\": {},\n  \"headers\": {\n    \"Content-Length\": \"59\",\n    \"Content-Type\": \"application/json\",\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\"\n  },\n  \"data\": \"{\\n  \\\"id\\\": 42,\\n  \\\"name\\\": \\\"Ada Lovelace\\\",\\n  \\\"role\\\": \\\"admin\\\"\\n}\",\n  \"json\": {\n    \"id\": 42,\n    \"name\": \"Ada Lovelace\",\n    \"role\": \"admin\"\n  },\n  \"origin\": \"203.0.113.42\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Echo a PATCH",
					"request": {
						"method": "PATCH",
						"header": [
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n  \"role\": \"viewer\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/patch"
						},
						"description": "The same echo for PATCH, handy for partial updates."
					},
					"response": [
						{
							"name": "Echo",
							"originalRequest": {
								"method": "PATCH",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"body": {
									"mode": "raw",
									"raw": "{\n  \"role\": \"viewer\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/patch"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "406"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"PATCH\",\n  \"url\": \"https://playground.tetiva.app/patch\",\n  \"args\": {},\n  \"headers\": {\n    \"Content-Length\": \"22\",\n    \"Content-Type\": \"application/json\",\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\"\n  },\n  \"data\": \"{\\n  \\\"role\\\": \\\"viewer\\\"\\n}\",\n  \"json\": {\n    \"role\": \"viewer\"\n  },\n  \"origin\": \"203.0.113.42\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Echo a DELETE",
					"request": {
						"method": "DELETE",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/delete?id=42"
						},
						"description": "The same echo for DELETE. A body is allowed and comes back too."
					},
					"response": [
						{
							"name": "Echo",
							"originalRequest": {
								"method": "DELETE",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/delete?id=42"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "314"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"DELETE\",\n  \"url\": \"https://playground.tetiva.app/delete?id=42\",\n  \"args\": {\n    \"id\": \"42\"\n  },\n  \"headers\": {\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\"\n  },\n  \"data\": \"\",\n  \"json\": null,\n  \"origin\": \"203.0.113.42\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Any method, any path",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n  \"status\": \"shipped\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/anything/orders/42?dry_run=true"
						},
						"description": "`/anything` and every path under it echo any method, custom ones included, so you can stand in for a route that doesn't exist yet."
					},
					"response": [
						{
							"name": "Echo",
							"originalRequest": {
								"method": "POST",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"body": {
									"mode": "raw",
									"raw": "{\n  \"status\": \"shipped\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/anything/orders/42?dry_run=true"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "462"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"POST\",\n  \"url\": \"https://playground.tetiva.app/anything/orders/42?dry_run=true\",\n  \"args\": {\n    \"dry_run\": \"true\"\n  },\n  \"headers\": {\n    \"Content-Length\": \"25\",\n    \"Content-Type\": \"application/json\",\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\"\n  },\n  \"data\": \"{\\n  \\\"status\\\": \\\"shipped\\\"\\n}\",\n  \"json\": {\n    \"status\": \"shipped\"\n  },\n  \"origin\": \"203.0.113.42\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "See my headers",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "X-Debug",
								"value": "1"
							}
						],
						"url": {
							"raw": "https://playground.tetiva.app/headers"
						},
						"description": "Returns only the headers the server received. Useful to check what your client, proxy or SDK adds."
					},
					"response": [
						{
							"name": "Your headers",
							"originalRequest": {
								"method": "GET",
								"header": [
									{
										"key": "X-Debug",
										"value": "1"
									}
								],
								"url": {
									"raw": "https://playground.tetiva.app/headers"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "167"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"headers\": {\n    \"Host\": \"playground.tetiva.app\",\n    \"User-Agent\": \"curl/8.7.1\",\n    \"X-Debug\": \"1\"\n  },\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				}
			]
		},
		{
			"name": "REST · Status codes and delays",
			"description": "Make the server fail or stall on purpose: any status from 200 to 599, or a wait of up to 10 seconds.",
			"item": [
				{
					"name": "Any status code",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/status/418"
						},
						"description": "Answers with the status in the path, from 200 to 599. Redirects point to `/get`, 401 adds `WWW-Authenticate`, 429 and 503 add `Retry-After`."
					},
					"response": [
						{
							"name": "I'm a teapot",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/status/418"
								}
							},
							"status": "I'm a teapot",
							"code": 418,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "104"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"status\": 418,\n  \"reason\": \"I'm a teapot\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						},
						{
							"name": "Service unavailable",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/status/418"
								}
							},
							"status": "Service Unavailable",
							"code": 503,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "111"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								},
								{
									"key": "retry-after",
									"value": "5"
								}
							],
							"body": "{\n  \"status\": 503,\n  \"reason\": \"Service Unavailable\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Slow response",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/delay/2"
						},
						"description": "Waits the number of seconds in the path, up to 10, then answers; fractions work too, as in `/delay/0.5`. Good for testing timeouts and loading states."
					},
					"response": [
						{
							"name": "After 2 seconds",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/delay/2"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "237"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"method\": \"GET\",\n  \"url\": \"https://playground.tetiva.app/delay/2\",\n  \"args\": {},\n  \"delay\": 2,\n  \"started_at\": \"2026-10-17T09:30:00Z\",\n  \"finished_at\": \"2026-10-17T09:30:02Z\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				}
			]
		},
		{
			"name": "REST · Auth",
			"description": "Check that your client sends credentials, and that it copes with the 401 when it doesn't.",
			"item": [
				{
					"name": "Bearer auth",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/bearer"
						},
						"auth": {
							"type": "bearer",
							"bearer": [
								{
									"key": "token",
									"value": "test-token"
								}
							]
						},
						"description": "Any non-empty token passes and comes back in `token`. Without `Authorization: Bearer …` you get 401 with `WWW-Authenticate: Bearer`."
					},
					"response": [
						{
							"name": "With a token",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/bearer"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "109"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"authenticated\": true,\n  \"token\": \"test-token\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						},
						{
							"name": "No Authorization header",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/bearer"
								}
							},
							"status": "Unauthorized",
							"code": 401,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "128"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								},
								{
									"key": "www-authenticate",
									"value": "Bearer realm=\"playground\""
								}
							],
							"body": "{\n  \"authenticated\": false,\n  \"error\": \"missing Authorization header\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Basic auth",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/basic-auth/tetiva/playground"
						},
						"auth": {
							"type": "basic",
							"basic": [
								{
									"key": "username",
									"value": "tetiva"
								},
								{
									"key": "password",
									"value": "playground"
								}
							]
						},
						"description": "Passes when the Basic credentials match the user and password in the path, here `tetiva` / `playground`. Anything else gets 401."
					},
					"response": [
						{
							"name": "Matching credentials",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/basic-auth/tetiva/playground"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "104"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"authenticated\": true,\n  \"user\": \"tetiva\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						},
						{
							"name": "Wrong password",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/basic-auth/tetiva/playground"
								}
							},
							"status": "Unauthorized",
							"code": 401,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "122"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								},
								{
									"key": "www-authenticate",
									"value": "Basic realm=\"playground\""
								}
							],
							"body": "{\n  \"authenticated\": false,\n  \"error\": \"wrong user or password\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				}
			]
		},
		{
			"name": "REST · Fake data",
			"description": "Five fake users for lists, tables and pagination. The data is the same every time, and `POST /users` answers as if it worked but stores nothing.",
			"item": [
				{
					"name": "Fake users",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/users?limit=3"
						},
						"description": "A page of fake users. `limit` takes 1 to 5, and `next` links to the following page until it is `null`."
					},
					"response": [
						{
							"name": "First page",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/users?limit=3"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "576"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"data\": [\n    {\n      \"id\": 1,\n      \"name\": \"Mila Novak\",\n      \"email\": \"mila.novak@example.com\",\n      \"role\": \"admin\",\n      \"created_at\": \"2026-03-02T09:14:00Z\"\n    },\n    {\n      \"id\": 2,\n      \"name\": \"Jonas Berg\",\n      \"email\": \"jonas.berg@example.com\",\n      \"role\": \"editor\",\n      \"created_at\": \"2026-04-18T16:40:00Z\"\n    },\n    {\n      \"id\": 3,\n      \"name\": \"Priya Raman\",\n      \"email\": \"priya.raman@example.com\",\n      \"role\": \"viewer\",\n      \"created_at\": \"2026-05-27T11:05:00Z\"\n    }\n  ],\n  \"total\": 5,\n  \"limit\": 3,\n  \"next\": \"/users?limit=3&after=3\"\n}\n"
						}
					]
				},
				{
					"name": "One fake user",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://playground.tetiva.app/users/2"
						},
						"description": "One user by id, from 1 to 5. Any other id gets 404 with a hint."
					},
					"response": [
						{
							"name": "Found",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/users/2"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "135"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"id\": 2,\n  \"name\": \"Jonas Berg\",\n  \"email\": \"jonas.berg@example.com\",\n  \"role\": \"editor\",\n  \"created_at\": \"2026-04-18T16:40:00Z\"\n}\n"
						},
						{
							"name": "Unknown id",
							"originalRequest": {
								"method": "GET",
								"header": [],
								"url": {
									"raw": "https://playground.tetiva.app/users/2"
								}
							},
							"status": "Not Found",
							"code": 404,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "138"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"error\": \"not_found\",\n  \"message\": \"No user with id 9. Ids go from 1 to 5.\",\n  \"request_id\": \"00000000-0000-4000-8000-000000000001\"\n}\n"
						}
					]
				},
				{
					"name": "Create a user",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n  \"name\": \"Grace Hopper\",\n  \"email\": \"grace@example.com\",\n  \"role\": \"editor\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/users"
						},
						"description": "Checks `name` and `email` and answers 201 with the new user and a `Location` header. Nothing is stored: `stored` is `false`."
					},
					"response": [
						{
							"name": "Created, not stored",
							"originalRequest": {
								"method": "POST",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"body": {
									"mode": "raw",
									"raw": "{\n  \"name\": \"Grace Hopper\",\n  \"email\": \"grace@example.com\",\n  \"role\": \"editor\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/users"
								}
							},
							"status": "Created",
							"code": 201,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "151"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								},
								{
									"key": "location",
									"value": "https://playground.tetiva.app/users/6"
								}
							],
							"body": "{\n  \"id\": 6,\n  \"name\": \"Grace Hopper\",\n  \"email\": \"grace@example.com\",\n  \"role\": \"editor\",\n  \"created_at\": \"2026-10-17T09:30:00Z\",\n  \"stored\": false\n}\n"
						}
					]
				}
			]
		},
		{
			"name": "GraphQL",
			"description": "A small library at `https://playground.tetiva.app/graphql`: books, authors and one mutation. Introspection is on, so any GraphQL client can load the schema.",
			"item": [
				{
					"name": "Run a GraphQL query",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "graphql",
							"graphql": {
								"query": "query Books($first: Int) {\n  books(first: $first) {\n    id\n    title\n    author {\n      name\n    }\n  }\n}",
								"variables": "{\n  \"first\": 2\n}"
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/graphql"
						},
						"description": "Lists books with their authors. `first` takes 1 to 50; a field that doesn't exist gets an error that lists the real ones."
					},
					"response": [
						{
							"name": "Two books",
							"originalRequest": {
								"method": "POST",
								"header": [],
								"body": {
									"mode": "graphql",
									"graphql": {
										"query": "query Books($first: Int) {\n  books(first: $first) {\n    id\n    title\n    author {\n      name\n    }\n  }\n}",
										"variables": "{\n  \"first\": 2\n}"
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/graphql"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "304"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"data\": {\n    \"books\": [\n      {\n        \"id\": \"1\",\n        \"title\": \"Frankenstein\",\n        \"author\": {\n          \"name\": \"Mary Shelley\"\n        }\n      },\n      {\n        \"id\": \"2\",\n        \"title\": \"Moby-Dick\",\n        \"author\": {\n          \"name\": \"Herman Melville\"\n        }\n      }\n    ]\n  }\n}\n"
						},
						{
							"name": "Unknown field",
							"originalRequest": {
								"method": "POST",
								"header": [],
								"body": {
									"mode": "graphql",
									"graphql": {
										"query": "query Books($first: Int) {\n  books(first: $first) {\n    id\n    title\n    author {\n      name\n    }\n  }\n}",
										"variables": "{\n  \"first\": 2\n}"
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/graphql"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "233"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"errors\": [\n    {\n      \"message\": \"Cannot query field \\\"isbn\\\" on type \\\"Book\\\". Fields on Book: id, title, year, author.\",\n      \"locations\": [\n        {\n          \"line\": 5,\n          \"column\": 5\n        }\n      ]\n    }\n  ]\n}\n"
						}
					]
				},
				{
					"name": "One book by id",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "graphql",
							"graphql": {
								"query": "query Book($id: ID!) {\n  book(id: $id) {\n    title\n    year\n    author {\n      name\n    }\n  }\n}",
								"variables": "{\n  \"id\": \"3\"\n}"
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/graphql"
						},
						"description": "Fetches one book. An unknown id returns `\"book\": null`, not an error."
					},
					"response": [
						{
							"name": "One book",
							"originalRequest": {
								"method": "POST",
								"header": [],
								"body": {
									"mode": "graphql",
									"graphql": {
										"query": "query Book($id: ID!) {\n  book(id: $id) {\n    title\n    year\n    author {\n      name\n    }\n  }\n}",
										"variables": "{\n  \"id\": \"3\"\n}"
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/graphql"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "151"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"data\": {\n    \"book\": {\n      \"title\": \"The Time Machine\",\n      \"year\": 1895,\n      \"author\": {\n        \"name\": \"H. G. Wells\"\n      }\n    }\n  }\n}\n"
						}
					]
				},
				{
					"name": "Add a book",
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "graphql",
							"graphql": {
								"query": "mutation AddBook($title: String!, $authorId: ID!) {\n  addBook(title: $title, authorId: $authorId) {\n    id\n    title\n    author {\n      name\n    }\n  }\n}",
								"variables": "{\n  \"title\": \"Carmilla\",\n  \"authorId\": \"a5\"\n}"
							}
						},
						"url": {
							"raw": "https://playground.tetiva.app/graphql"
						},
						"description": "A mutation that returns the new book with id `6`. Nothing is stored: `extensions.stored` is `false`."
					},
					"response": [
						{
							"name": "Added, not stored",
							"originalRequest": {
								"method": "POST",
								"header": [],
								"body": {
									"mode": "graphql",
									"graphql": {
										"query": "mutation AddBook($title: String!, $authorId: ID!) {\n  addBook(title: $title, authorId: $authorId) {\n    id\n    title\n    author {\n      name\n    }\n  }\n}",
										"variables": "{\n  \"title\": \"Carmilla\",\n  \"authorId\": \"a5\"\n}"
									}
								},
								"url": {
									"raw": "https://playground.tetiva.app/graphql"
								}
							},
							"status": "OK",
							"code": 200,
							"_postman_previewlanguage": "json",
							"header": [
								{
									"key": "content-type",
									"value": "application/json; charset=utf-8"
								},
								{
									"key": "content-length",
									"value": "191"
								},
								{
									"key": "x-request-id",
									"value": "00000000-0000-4000-8000-000000000001"
								},
								{
									"key": "access-control-allow-origin",
									"value": "*"
								},
								{
									"key": "ratelimit-limit",
									"value": "60"
								},
								{
									"key": "ratelimit-remaining",
									"value": "59"
								}
							],
							"body": "{\n  \"data\": {\n    \"addBook\": {\n      \"id\": \"6\",\n      \"title\": \"Carmilla\",\n      \"author\": {\n        \"name\": \"Sheridan Le Fanu\"\n      }\n    }\n  },\n  \"extensions\": {\n    \"stored\": false\n  }\n}\n"
						}
					]
				}
			]
		},
		{
			"name": "gRPC",
			"description": "`echo.v1.EchoService` on `playground.tetiva.app:443` with TLS and server reflection, so clients find the methods without a `.proto` file.\n\n**Reflection**\n\n```bash\ngrpcurl playground.tetiva.app:443 list\ngrpcurl playground.tetiva.app:443 describe echo.v1.EchoService\n```\n\n**Streams.** `ServerStream` and `Chat` stream, so they are not in this collection. Run them with grpcurl:\n\n```bash\ngrpcurl -d '{\"text\":\"ping\",\"count\":3,\"interval_ms\":500}' playground.tetiva.app:443 echo.v1.EchoService/ServerStream\ngrpcurl -d @ playground.tetiva.app:443 echo.v1.EchoService/Chat <<'EOF'\n{\"text\":\"hello\"}\n{\"text\":\"still there?\"}\nEOF\n```",
			"item": []
		},
		{
			"name": "WebSocket",
			"description": "Text and binary frames up to 64 KB. `/ws` closes after 60 seconds without a message, with `1000 Normal Closure`; every session ends after 10 minutes.",
			"item": []
		}
	]
}
