1---
2title: REST API
3kind: documentation
4weight: 80
5restrictedtoc: true
6---
7
8This document is the authoritative specification of the OPA REST API.
9
10##  Policy API
11
12The Policy API exposes CRUD endpoints for managing policy modules. Policy modules can be added, removed, and modified at any time.
13
14The identifiers given to policy modules are only used for management purposes. They are not used outside of the Policy API.
15
16### List Policies
17
18```http
19GET /v1/policies HTTP/1.1
20```
21
22List policy modules.
23
24
25#### Status Codes
26
27- **200** - no error
28- **500** - server error
29
30#### Example Request
31
32```http
33GET /v1/policies HTTP/1.1
34```
35
36#### Example Response
37
38```http
39HTTP/1.1 200 OK
40Content-Type: application/json
41```
42
43```json
44{
45  "result": [
46    {
47      "id": "example2",
48      "raw": "package opa.examples\n\nimport data.servers\n\nviolations[server] {\n\tserver = servers[_]\n\tserver.protocols[_] = \"http\"\n\tpublic_servers[server]\n}\n",
49      "ast": {
50        "package": {
51          "path": [
52            {
53              "type": "var",
54              "value": "data"
55            },
56            {
57              "type": "string",
58              "value": "opa"
59            },
60            {
61              "type": "string",
62              "value": "examples"
63            }
64          ]
65        },
66        "rules": [
67          {
68            "head": {
69              "name": "violations",
70              "key": {
71                "type": "var",
72                "value": "server"
73              }
74            },
75            "body": [
76              {
77                "index": 0,
78                "terms": [
79                  {
80                    "type": "string",
81                    "value": "eq"
82                  },
83                  {
84                    "type": "var",
85                    "value": "server"
86                  },
87                  {
88                    "type": "ref",
89                    "value": [
90                      {
91                        "type": "var",
92                        "value": "data"
93                      },
94                      {
95                        "type": "string",
96                        "value": "servers"
97                      },
98                      {
99                        "type": "var",
100                        "value": "$0"
101                      }
102                    ]
103                  }
104                ]
105              },
106              {
107                "index": 1,
108                "terms": [
109                  {
110                    "type": "string",
111                    "value": "eq"
112                  },
113                  {
114                    "type": "ref",
115                    "value": [
116                      {
117                        "type": "var",
118                        "value": "server"
119                      },
120                      {
121                        "type": "string",
122                        "value": "protocols"
123                      },
124                      {
125                        "type": "var",
126                        "value": "$1"
127                      }
128                    ]
129                  },
130                  {
131                    "type": "string",
132                    "value": "http"
133                  }
134                ]
135              },
136              {
137                "index": 2,
138                "terms": {
139                  "type": "ref",
140                  "value": [
141                    {
142                      "type": "var",
143                      "value": "data"
144                    },
145                    {
146                      "type": "string",
147                      "value": "opa"
148                    },
149                    {
150                      "type": "string",
151                      "value": "examples"
152                    },
153                    {
154                      "type": "string",
155                      "value": "public_servers"
156                    },
157                    {
158                      "type": "var",
159                      "value": "server"
160                    }
161                  ]
162                }
163              }
164            ]
165          }
166        ]
167      }
168    },
169    {
170      "id": "example1",
171      "raw": "package opa.examples\n\nimport data.servers\nimport data.networks\nimport data.ports\n\npublic_servers[server] {\n\tserver = servers[_]\n\tserver.ports[_] = ports[k].id\n\tports[k].networks[_] = networks[m].id\n\tnetworks[m].public = true\n}\n",
172      "ast": {
173        "package": {
174          "path": [
175            {
176              "type": "var",
177              "value": "data"
178            },
179            {
180              "type": "string",
181              "value": "opa"
182            },
183            {
184              "type": "string",
185              "value": "examples"
186            }
187          ]
188        },
189        "rules": [
190          {
191            "head": {
192              "name": "public_servers",
193              "key": {
194                "type": "var",
195                "value": "server"
196              }
197            },
198            "body": [
199              {
200                "index": 0,
201                "terms": [
202                  {
203                    "type": "string",
204                    "value": "eq"
205                  },
206                  {
207                    "type": "var",
208                    "value": "server"
209                  },
210                  {
211                    "type": "ref",
212                    "value": [
213                      {
214                        "type": "var",
215                        "value": "data"
216                      },
217                      {
218                        "type": "string",
219                        "value": "servers"
220                      },
221                      {
222                        "type": "var",
223                        "value": "$0"
224                      }
225                    ]
226                  }
227                ]
228              },
229              {
230                "index": 1,
231                "terms": [
232                  {
233                    "type": "string",
234                    "value": "eq"
235                  },
236                  {
237                    "type": "ref",
238                    "value": [
239                      {
240                        "type": "var",
241                        "value": "server"
242                      },
243                      {
244                        "type": "string",
245                        "value": "ports"
246                      },
247                      {
248                        "type": "var",
249                        "value": "$1"
250                      }
251                    ]
252                  },
253                  {
254                    "type": "ref",
255                    "value": [
256                      {
257                        "type": "var",
258                        "value": "data"
259                      },
260                      {
261                        "type": "string",
262                        "value": "ports"
263                      },
264                      {
265                        "type": "var",
266                        "value": "k"
267                      },
268                      {
269                        "type": "string",
270                        "value": "id"
271                      }
272                    ]
273                  }
274                ]
275              },
276              {
277                "index": 2,
278                "terms": [
279                  {
280                    "type": "string",
281                    "value": "eq"
282                  },
283                  {
284                    "type": "ref",
285                    "value": [
286                      {
287                        "type": "var",
288                        "value": "data"
289                      },
290                      {
291                        "type": "string",
292                        "value": "ports"
293                      },
294                      {
295                        "type": "var",
296                        "value": "k"
297                      },
298                      {
299                        "type": "string",
300                        "value": "networks"
301                      },
302                      {
303                        "type": "var",
304                        "value": "$2"
305                      }
306                    ]
307                  },
308                  {
309                    "type": "ref",
310                    "value": [
311                      {
312                        "type": "var",
313                        "value": "data"
314                      },
315                      {
316                        "type": "string",
317                        "value": "networks"
318                      },
319                      {
320                        "type": "var",
321                        "value": "m"
322                      },
323                      {
324                        "type": "string",
325                        "value": "id"
326                      }
327                    ]
328                  }
329                ]
330              },
331              {
332                "index": 3,
333                "terms": [
334                  {
335                    "type": "string",
336                    "value": "eq"
337                  },
338                  {
339                    "type": "ref",
340                    "value": [
341                      {
342                        "type": "var",
343                        "value": "data"
344                      },
345                      {
346                        "type": "string",
347                        "value": "networks"
348                      },
349                      {
350                        "type": "var",
351                        "value": "m"
352                      },
353                      {
354                        "type": "string",
355                        "value": "public"
356                      }
357                    ]
358                  },
359                  {
360                    "type": "boolean",
361                    "value": true
362                  }
363                ]
364              }
365            ]
366          }
367        ]
368      }
369    }
370  ]
371}
372
373```
374
375### Get a Policy
376
377```
378GET /v1/policies/<id>
379```
380
381Get a policy module.
382
383#### Query Parameters
384
385- **pretty** - If parameter is `true`, response will formatted for humans.
386
387#### Status Codes
388
389- **200** - no error
390- **404** - not found
391- **500** - server error
392
393#### Example Request
394
395```http
396GET /v1/policies/example1 HTTP/1.1
397```
398
399#### Example Response
400
401```http
402HTTP/1.1 200 OK
403Content-Type: application/json
404```
405
406```json
407{
408  "result": {
409    "id": "example1",
410    "raw": "package opa.examples\n\nimport data.servers\nimport data.networks\nimport data.ports\n\npublic_servers[server] {\n\tserver = servers[_]\n\tserver.ports[_] = ports[k].id\n\tports[k].networks[_] = networks[m].id\n\tnetworks[m].public = true\n}\n",
411    "ast": {
412      "package": {
413        "path": [
414          {
415            "type": "var",
416            "value": "data"
417          },
418          {
419            "type": "string",
420            "value": "opa"
421          },
422          {
423            "type": "string",
424            "value": "examples"
425          }
426        ]
427      },
428      "rules": [
429        {
430          "head": {
431            "name": "public_servers",
432            "key": {
433              "type": "var",
434              "value": "server"
435            }
436          },
437          "body": [
438            {
439              "index": 0,
440              "terms": [
441                {
442                  "type": "string",
443                  "value": "eq"
444                },
445                {
446                  "type": "var",
447                  "value": "server"
448                },
449                {
450                  "type": "ref",
451                  "value": [
452                    {
453                      "type": "var",
454                      "value": "data"
455                    },
456                    {
457                      "type": "string",
458                      "value": "servers"
459                    },
460                    {
461                      "type": "var",
462                      "value": "$0"
463                    }
464                  ]
465                }
466              ]
467            },
468            {
469              "index": 1,
470              "terms": [
471                {
472                  "type": "string",
473                  "value": "eq"
474                },
475                {
476                  "type": "ref",
477                  "value": [
478                    {
479                      "type": "var",
480                      "value": "server"
481                    },
482                    {
483                      "type": "string",
484                      "value": "ports"
485                    },
486                    {
487                      "type": "var",
488                      "value": "$1"
489                    }
490                  ]
491                },
492                {
493                  "type": "ref",
494                  "value": [
495                    {
496                      "type": "var",
497                      "value": "data"
498                    },
499                    {
500                      "type": "string",
501                      "value": "ports"
502                    },
503                    {
504                      "type": "var",
505                      "value": "k"
506                    },
507                    {
508                      "type": "string",
509                      "value": "id"
510                    }
511                  ]
512                }
513              ]
514            },
515            {
516              "index": 2,
517              "terms": [
518                {
519                  "type": "string",
520                  "value": "eq"
521                },
522                {
523                  "type": "ref",
524                  "value": [
525                    {
526                      "type": "var",
527                      "value": "data"
528                    },
529                    {
530                      "type": "string",
531                      "value": "ports"
532                    },
533                    {
534                      "type": "var",
535                      "value": "k"
536                    },
537                    {
538                      "type": "string",
539                      "value": "networks"
540                    },
541                    {
542                      "type": "var",
543                      "value": "$2"
544                    }
545                  ]
546                },
547                {
548                  "type": "ref",
549                  "value": [
550                    {
551                      "type": "var",
552                      "value": "data"
553                    },
554                    {
555                      "type": "string",
556                      "value": "networks"
557                    },
558                    {
559                      "type": "var",
560                      "value": "m"
561                    },
562                    {
563                      "type": "string",
564                      "value": "id"
565                    }
566                  ]
567                }
568              ]
569            },
570            {
571              "index": 3,
572              "terms": [
573                {
574                  "type": "string",
575                  "value": "eq"
576                },
577                {
578                  "type": "ref",
579                  "value": [
580                    {
581                      "type": "var",
582                      "value": "data"
583                    },
584                    {
585                      "type": "string",
586                      "value": "networks"
587                    },
588                    {
589                      "type": "var",
590                      "value": "m"
591                    },
592                    {
593                      "type": "string",
594                      "value": "public"
595                    }
596                  ]
597                },
598                {
599                  "type": "boolean",
600                  "value": true
601                }
602              ]
603            }
604          ]
605        }
606      ]
607    }
608  }
609}
610```
611
612### Create or Update a Policy
613
614```
615PUT /v1/policies/<id>
616Content-Type: text/plain
617```
618
619Create or update a policy module.
620
621If the policy module does not exist, it is created. If the policy module already exists, it is replaced.
622
623#### Query Parameters
624
625- **pretty** - If parameter is `true`, response will formatted for humans.
626- **metrics** - Return compiler performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
627
628#### Status Codes
629
630- **200** - no error
631- **400** - bad request
632- **500** - server error
633
634Before accepting the request, the server will parse, compile, and install the policy module. If the policy module is invalid, one of these steps will fail and the server will respond with 400. The error message in the response will be set to indicate the source of the error.
635
636#### Example Request
637
638```http
639PUT /v1/policies/example1 HTTP/1.1
640Content-Type: text/plain
641```
642
643```live:put_example:module:read_only
644package opa.examples
645
646import data.servers
647import data.networks
648import data.ports
649
650public_servers[server] {
651  some k, m
652	server := servers[_]
653	server.ports[_] == ports[k].id
654	ports[k].networks[_] == networks[m].id
655	networks[m].public == true
656}
657```
658
659> cURL's `-d/--data` flag removes newline characters from input files. Use the `--data-binary` flag instead.
660
661#### Example Response
662
663```http
664HTTP/1.1 200 OK
665Content-Type: application/json
666```
667
668```json
669{}
670```
671
672### Delete a Policy
673
674```
675DELETE /v1/policies/<id>
676```
677
678Delete a policy module.
679
680#### Query Parameters
681
682- **pretty** - If parameter is `true`, response will formatted for humans.
683- **metrics** - Return compiler performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
684
685#### Status Codes
686
687- **200** - no error
688- **400** - bad request
689- **404** - not found
690- **500** - server error
691
692If other policy modules in the same package depend on rules in the policy module to be deleted, the server will return 400.
693
694#### Example Request
695
696```http
697DELETE /v1/policies/example2 HTTP/1.1
698```
699
700#### Example Response
701
702```http
703HTTP/1.1 200 OK
704Content-Type: application/json
705```
706
707```json
708{}
709```
710
711## Data API
712
713The Data API exposes endpoints for reading and writing documents in OPA. For an introduction to the different types of documents in OPA see [How Does OPA Work?](../#how-does-opa-work).
714
715### Get a Document
716
717```
718GET /v1/data/{path:.+}
719```
720
721Get a document.
722
723The path separator is used to access values inside object and array documents. If the path indexes into an array, the server will attempt to convert the array index to an integer. If the path element cannot be converted to an integer, the server will respond with 404.
724
725#### Query Parameters
726
727- **input** - Provide an input document. Format is a JSON value that will be used as the value for the input document.
728- **pretty** - If parameter is `true`, response will formatted for humans.
729- **provenance** - If parameter is `true`, response will include build/version info in addition to the result.  See [Provenance](#provenance) for more detail.
730- **explain** - Return query explanation in addition to result. Values: **full**.
731- **metrics** - Return query performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
732- **instrument** - Instrument query evaluation and return a superset of performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
733- **watch** - Set a watch on the data reference if the parameter is present. See [Watches](#watches) for more detail.
734
735#### Status Codes
736
737- **200** - no error
738- **400** - bad request
739- **500** - server error
740
741The server returns 400 if either:
742
743- The query requires the input document and the caller does not provide it.
744- The caller provides the input document but the query already defines it programmatically.
745
746The server returns 200 if the path refers to an undefined document. In this
747case, the response will not contain a `result` property.
748
749#### Response Message
750
751- **result** - The base or virtual document referred to by the URL path. If the
752  path is undefined, this key will be omitted.
753- **metrics** - If query metrics are enabled, this field contains query
754  performance metrics collected during the parse, compile, and evaluation steps.
755* **decision_id** - If decision logging is enabled, this field contains a string
756  that uniquely identifies the decision. The identifier will be included in the
757  decision log event for this decision. Callers can use the identifier for
758  correlation purposes.
759
760#### Example Request
761
762```http
763GET /v1/data/opa/examples/public_servers HTTP/1.1
764```
765
766#### Example Response
767
768```http
769HTTP/1.1 200 OK
770Content-Type: application/json
771```
772
773```json
774{
775  "result": [
776    {
777      "id": "s1",
778      "name": "app",
779      "ports": [
780        "p1",
781        "p2",
782        "p3"
783      ],
784      "protocols": [
785        "https",
786        "ssh"
787      ]
788    },
789    {
790      "id": "s4",
791      "name": "dev",
792      "ports": [
793        "p1",
794        "p2"
795      ],
796      "protocols": [
797        "http"
798      ]
799    }
800  ]
801}
802```
803
804#### Example Watch Request
805
806If we make the following GET request:
807
808```http
809GET /v1/data/servers?watch&pretty=true HTTP/1.1
810```
811
812Followed by these PATCH requests:
813
814```http
815PATCH /v1/data/servers HTTP/1.1
816Content-Type: application/json-patch+json
817```
818
819```json
820[
821    {"op": "add",
822     "path": "-",
823     "value": {
824         "id": "s5",
825         "name": "job",
826         "protocols": ["amqp"],
827         "ports": ["p3"]
828     }}
829]
830```
831
832```http
833PATCH /v1/data/servers HTTP/1.1
834Content-Type: application/json-patch+json
835```
836
837```json
838[
839    {
840     "op": "remove",
841     "path": "1"
842    }
843]
844```
845
846#### Example Watch Response
847
848The response below represents the response _after_ the chunked encoding has been processed.
849It is not complete, as further changes to `/data/servers` would cause more notifications to be streamed.
850
851```http
852HTTP/1.1 200 OK
853Content-Type: application/json
854Transfer-Encoding: chunked
855```
856
857```json
858{
859  "result": [
860    {
861      "id": "s1",
862      "name": "app",
863      "ports": [
864        "p1",
865        "p2",
866        "p3"
867      ],
868      "protocols": [
869        "https",
870        "ssh"
871      ]
872    },
873    {
874      "id": "s2",
875      "name": "db",
876      "ports": [
877        "p3"
878      ],
879      "protocols": [
880        "mysql"
881      ]
882    },
883    {
884      "id": "s3",
885      "name": "cache",
886      "ports": [
887        "p3"
888      ],
889      "protocols": [
890        "memcache",
891        "http"
892      ]
893    },
894    {
895      "id": "s4",
896      "name": "dev",
897      "ports": [
898        "p1",
899        "p2"
900      ],
901      "protocols": [
902        "http"
903      ]
904    }
905  ]
906}
907
908{
909  "result": [
910    {
911      "id": "s1",
912      "name": "app",
913      "ports": [
914        "p1",
915        "p2",
916        "p3"
917      ],
918      "protocols": [
919        "https",
920        "ssh"
921      ]
922    },
923    {
924      "id": "s2",
925      "name": "db",
926      "ports": [
927        "p3"
928      ],
929      "protocols": [
930        "mysql"
931      ]
932    },
933    {
934      "id": "s3",
935      "name": "cache",
936      "ports": [
937        "p3"
938      ],
939      "protocols": [
940        "memcache",
941        "http"
942      ]
943    },
944    {
945      "id": "s4",
946      "name": "dev",
947      "ports": [
948        "p1",
949        "p2"
950      ],
951      "protocols": [
952        "http"
953      ]
954    },
955    {
956      "id": "s5",
957      "name": "job",
958      "ports": [
959        "p3"
960      ],
961      "protocols": [
962        "amqp"
963      ]
964    }
965  ]
966}
967
968{
969  "result": [
970    {
971      "id": "s1",
972      "name": "app",
973      "ports": [
974        "p1",
975        "p2",
976        "p3"
977      ],
978      "protocols": [
979        "https",
980        "ssh"
981      ]
982    },
983    {
984      "id": "s3",
985      "name": "cache",
986      "ports": [
987        "p3"
988      ],
989      "protocols": [
990        "memcache",
991        "http"
992      ]
993    },
994    {
995      "id": "s4",
996      "name": "dev",
997      "ports": [
998        "p1",
999        "p2"
1000      ],
1001      "protocols": [
1002        "http"
1003      ]
1004    },
1005    {
1006      "id": "s5",
1007      "name": "job",
1008      "ports": [
1009        "p3"
1010      ],
1011      "protocols": [
1012        "amqp"
1013      ]
1014    }
1015  ]
1016}
1017```
1018
1019### Get a Document (with Input)
1020
1021```
1022POST /v1/data/{path:.+}
1023Content-Type: application/json
1024```
1025
1026```json
1027{
1028  "input": ...
1029}
1030```
1031
1032Get a document that requires input.
1033
1034The path separator is used to access values inside object and array documents. If the path indexes into an array, the server will attempt to convert the array index to an integer. If the path element cannot be converted to an integer, the server will respond with 404.
1035
1036The request body contains an object that specifies a value for [The input Document](../#the-input-document).
1037
1038#### Request Headers
1039
1040- **Content-Type: application/x-yaml**: Indicates the request body is a YAML encoded object.
1041
1042#### Query Parameters
1043
1044- **partial** - Use the partial evaluation (optimization) when evaluating the query.
1045- **pretty** - If parameter is `true`, response will formatted for humans.
1046- **provenance** - If parameter is `true`, response will include build/version info in addition to the result.  See [Provenance](#provenance) for more detail.
1047- **explain** - Return query explanation in addition to result. Values: **full**.
1048- **metrics** - Return query performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
1049- **instrument** - Instrument query evaluation and return a superset of performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
1050- **watch** - Set a watch on the data reference if the parameter is present. See [Watches](#watches) for more detail.
1051
1052#### Status Codes
1053
1054- **200** - no error
1055- **400** - bad request
1056- **500** - server error
1057
1058The server returns 400 if either:
1059
10601. The query requires an input document and the client did not supply one.
10612. The query already defines an input document and the client did supply one.
1062
1063The server returns 200 if the path refers to an undefined document. In this
1064case, the response will not contain a `result` property.
1065
1066#### Response Message
1067
1068- **result** - The base or virtual document referred to by the URL path. If the
1069  path is undefined, this key will be omitted.
1070- **metrics** - If query metrics are enabled, this field contains query
1071  performance metrics collected during the parse, compile, and evaluation steps.
1072* **decision_id** - If decision logging is enabled, this field contains a string
1073  that uniquely identifies the decision. The identifier will be included in the
1074  decision log event for this decision. Callers can use the identifier for
1075  correlation purposes.
1076
1077The examples below assume the following policy:
1078
1079```live:input_exmaple:module:read_only
1080package opa.examples
1081
1082import input.example.flag
1083
1084allow_request { flag == true }
1085```
1086
1087#### Example Request
1088
1089```http
1090POST /v1/data/opa/examples/allow_request HTTP/1.1
1091Content-Type: application/json
1092```
1093
1094```json
1095{
1096  "input": {
1097    "example": {
1098      "flag": true
1099    }
1100  }
1101}
1102```
1103
1104#### Example Response
1105
1106```http
1107HTTP/1.1 200 OK
1108Content-Type: application/json
1109```
1110
1111```json
1112{
1113  "result": true
1114}
1115```
1116
1117#### Example Request
1118
1119```http
1120POST /v1/data/opa/examples/allow_request HTTP/1.1
1121Content-Type: application/json
1122```
1123
1124```json
1125{
1126  "input": {
1127    "example": {
1128      "flag": false
1129    }
1130  }
1131}
1132```
1133
1134#### Example Response
1135
1136```http
1137HTTP/1.1 200 OK
1138```
1139
1140```json
1141{}
1142```
1143
1144### Get a Document (Webhook)
1145
1146```
1147POST /v0/data/{path:.+}
1148Content-Type: application/json
1149```
1150
1151Get a document from a webhook.
1152
1153Use this API if you are enforcing policy decisions via webhooks that have pre-defined
1154request/response formats. Note, the API path prefix is `/v0` instead of `/v1`.
1155
1156The request message body defines the content of the [The input
1157Document](../#the-input-document). The request message body
1158may be empty. The path separator is used to access values inside object and
1159array documents.
1160
1161#### Request Headers
1162
1163- **Content-Type: application/x-yaml**: Indicates the request body is a YAML encoded object.
1164
1165#### Query Parameters
1166
1167- **pretty** - If parameter is `true`, response will formatted for humans.
1168
1169#### Status Codes
1170
1171- **200** - no error
1172- **400** - bad request
1173- **404** - not found
1174- **500** - server error
1175
1176If the requested document is missing or undefined, the server will return 404 and the message body will contain an error object.
1177
1178The examples below assume the following policy:
1179
1180```live:webhook_example:module:read_only
1181package opa.examples
1182
1183import input.example.flag
1184
1185allow_request { flag == true }
1186```
1187
1188#### Example Request
1189
1190```http
1191POST /v0/data/opa/examples/allow_request HTTP/1.1
1192Content-Type: application/json
1193```
1194
1195```json
1196{
1197  "example": {
1198    "flag": true
1199  }
1200}
1201```
1202
1203#### Example Response
1204
1205```http
1206HTTP/1.1 200 OK
1207Content-Type: application/json
1208```
1209
1210```json
1211true
1212```
1213
1214### Create or Overwrite a Document
1215
1216```
1217PUT /v1/data/{path:.+}
1218Content-Type: application/json
1219```
1220
1221Create or overwrite a document.
1222
1223If the path does not refer to an existing document, the server will attempt to create all of the necessary containing documents. This behavior is similar in principle to the Unix command `mkdir -p`.
1224
1225The server will respect the `If-None-Match` header if it is set to `*`. In this case, the server will not overwrite an existing document located at the path.
1226
1227#### Status Codes
1228
1229- **204** - no content (success)
1230- **304** - not modified
1231- **400** - bad request
1232- **404** - write conflict
1233- **500** - server error
1234
1235If the path refers to a virtual document or a conflicting base document the server will respond with 404. A base document conflict will occur if the parent portion of the path refers to a non-object document.
1236
1237#### Example Request To Initialize Document With If-None-Match
1238
1239```http
1240PUT /v1/data/us-west/servers HTTP/1.1
1241Content-Type: application/json
1242If-None-Match: *
1243```
1244
1245```json
1246{}
1247```
1248
1249#### Example Response If Document Already Exists
1250
1251```http
1252HTTP/1.1 304 Not Modified
1253```
1254
1255#### Example Response If Document Does Not Exist
1256
1257```http
1258HTTP/1.1 204 No Content
1259```
1260
1261### Patch a Document
1262
1263```
1264PATCH /v1/data/{path:.+}
1265Content-Type: application/json-patch+json
1266```
1267
1268Update a document.
1269
1270The path separator is used to access values inside object and array documents. If the path indexes into an array, the server will attempt to convert the array index to an integer. If the path element cannot be converted to an integer, the server will respond with 404.
1271
1272The server accepts updates encoded as JSON Patch operations. The message body of the request should contain a JSON encoded array containing one or more JSON Patch operations. Each operation specifies the operation type, path, and an optional value. For more information on JSON Patch, see [RFC 6902](https://tools.ietf.org/html/rfc6902).
1273
1274#### Status Codes
1275
1276- **204** - no content (success)
1277- **400** - bad request
1278- **404** - not found
1279- **500** - server error
1280
1281The effective path of the JSON Patch operation is obtained by joining the path portion of the URL with the path value from the operation(s) contained in the message body. In all cases, the parent of the effective path MUST refer to an existing document, otherwise the server returns 404. In the case of **remove** and **replace** operations, the effective path MUST refer to an existing document, otherwise the server returns 404.
1282
1283#### Example Request
1284
1285```http
1286PATCH /v1/data/servers HTTP/1.1
1287Content-Type: application/json-patch+json
1288```
1289
1290```json
1291[
1292    {"op": "add",
1293     "path": "-",
1294     "value": {
1295         "id": "s5",
1296         "name": "job",
1297         "protocols": ["amqp"],
1298         "ports": ["p3"]
1299     }}
1300]
1301```
1302
1303#### Example Response
1304
1305```http
1306HTTP/1.1 204 No Content
1307```
1308
1309### Delete a Document
1310
1311```
1312DELETE /v1/data/{path:.+}
1313```
1314
1315Delete a document.
1316
1317The server processes the DELETE method as if the client had sent a PATCH request containing a single remove operation.
1318
1319#### Status Codes
1320
1321- **204** - no content (success)
1322- **404** - not found
1323- **500** - server error
1324
1325If the path refers to a non-existent document, the server returns 404.
1326
1327#### Example Request
1328
1329```http
1330DELETE /v1/data/servers HTTP/1.1
1331```
1332
1333#### Example Response
1334
1335```http
1336HTTP/1.1 204 No Content
1337```
1338
1339## Query API
1340
1341### Execute a Simple Query
1342
1343```
1344POST /
1345Content-Type: application/json
1346```
1347
1348Execute a simple query.
1349
1350OPA serves POST requests without a URL path by querying for the document at
1351path `/data/system/main`. The content of that document defines the response
1352entirely.
1353
1354#### Request Headers
1355
1356- **Content-Type: application/x-yaml**: Indicates the request body is a YAML encoded object.
1357
1358#### Query Parameters
1359
1360- **pretty** - If parameter is `true`, response will formatted for humans.
1361
1362#### Status Codes
1363
1364- **200** - no error
1365- **400** - bad request
1366- **404** - not found
1367- **500** - server error
1368
1369If the default decision (defaulting to `/system/main`) is undefined, the server returns 404.
1370
1371The policy example below shows how to define a rule that will
1372produce a value for the `/data/system/main` document. You can configure OPA
1373to use a different URL path to serve these queries. See the [Configuration Reference](../configuration)
1374for more information.
1375
1376The request message body is mapped to the [Input Document](../#the-input-document).
1377
1378```http
1379PUT /v1/policies/example1 HTTP/1.1
1380Content-Type: text/plain
1381```
1382
1383```live:system_example:module:read_only
1384package system
1385
1386main = msg {
1387  msg := sprintf("hello, %v", input.user)
1388}
1389```
1390
1391#### Example Request
1392
1393```http
1394POST /
1395Content-Type: application/json
1396```
1397
1398```json
1399{
1400  "user": ["alice"]
1401}
1402```
1403
1404#### Example Response
1405
1406```http
1407HTTP/1.1 200 OK
1408Content-Type: application/json
1409```
1410
1411```json
1412"hello, alice"
1413```
1414
1415### Execute an Ad-hoc Query
1416
1417Execute an ad-hoc query and return bindings for variables found in the query.
1418
1419```
1420GET /v1/query
1421```
1422
1423#### Query Parameters
1424
1425- **q** - The ad-hoc query to execute. OPA will parse, compile, and execute the query represented by the parameter value. The value MUST be URL encoded. Only used in GET method. For POST method the query is sent as part of the request body and this parameter is not used.
1426- **pretty** - If parameter is `true`, response will formatted for humans.
1427- **explain** - Return query explanation in addition to result. Values: **full**.
1428- **metrics** - Return query performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
1429- **watch** - Set a watch on the query if the parameter is present. See [Watches](#watches) for more detail.
1430
1431#### Status Codes
1432
1433- **200** - no error
1434- **400** - bad request
1435- **404** - watch ID not found
1436- **500** - server error
1437- **501** - streaming not implemented
1438
1439For queries that have large JSON values it is recommended to use the `POST` method with the query included as the `POST` body
1440
1441```
1442POST /v1/query HTTP/1.1
1443Content-Type: application/json
1444```
1445
1446```json
1447{
1448  "query": "data.servers[i].ports[_] = \"p2\"; data.servers[i].name = name"
1449}
1450```
1451
1452#### Example Request
1453
1454```
1455GET /v1/query?q=data.servers[i].ports[_] = "p2"; data.servers[i].name = name HTTP/1.1
1456```
1457
1458#### Example Response
1459
1460```http
1461HTTP/1.1 200 OK
1462Content-Type: application/json
1463```
1464
1465```json
1466{
1467  "result": [
1468    {
1469      "i": 3,
1470      "name": "dev"
1471    },
1472    {
1473      "i": 0,
1474      "name": "app"
1475    }
1476  ]
1477}
1478```
1479
1480## Compile API
1481
1482### Partially Evaluate a Query
1483
1484```http
1485POST /v1/compile
1486Content-Type: application/json
1487```
1488
1489Partially evaluate a query.
1490
1491The [Compile API](#compile-api) allows you to partially evaluate Rego queries
1492and obtain a simplified version of the policy. For more details on Partial
1493Evaluation in OPA, see [this post on blog.openpolicyagent.org](https://blog.openpolicyagent.org/partial-evaluation-162750eaf422).
1494
1495#### Request Body
1496
1497Compile API requests contain the following fields:
1498
1499| Field | Type | Requried | Description |
1500| --- | --- | --- | --- |
1501| `query` | `string` | Yes | The query to partially evaluate and compile. |
1502| `input` | `any` | No | The input document to use during partial evaluation (default: undefined). |
1503| `unknowns` | `array[string]` | No | The terms to treat as unknown during partial evaluation (default: `["input"]`]). |
1504
1505#### Query Parameters
1506
1507- **pretty** - If parameter is `true`, response will formatted for humans.
1508- **explain** - Return query explanation in addition to result. Values: **full**.
1509- **metrics** - Return query performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
1510- **instrument** - Instrument query evaluation and return a superset of performance metrics in addition to result. See [Performance Metrics](#performance-metrics) for more detail.
1511
1512#### Status Codes
1513
1514- **200** - no error
1515- **400** - bad request
1516- **500** - server error
1517
1518The example below assumes that OPA has been given the following policy:
1519
1520```live:compile_example:module:read_only
1521package example
1522
1523allow {
1524  input.subject.clearance_level >= data.reports[_].clearance_level
1525}
1526```
1527
1528#### Example Request
1529
1530```http
1531POST /v1/compile HTTP/1.1
1532Content-Type: application/json
1533```
1534
1535```json
1536{
1537  "query": "data.example.allow == true",
1538  "input": {
1539    "subject": {
1540      "clearance_level": 4
1541    }
1542  },
1543  "unknowns": [
1544    "data.reports"
1545  ]
1546}
1547```
1548
1549#### Example Response
1550
1551```http
1552HTTP/1.1 200 OK
1553Content-Type: application/json
1554```
1555
1556```json
1557{
1558  "result": {
1559    "queries": [
1560      [
1561        {
1562          "index": 0,
1563          "terms": [
1564            {
1565              "type": "ref",
1566              "value": [
1567                {
1568                  "type": "var",
1569                  "value": "gte"
1570                }
1571              ]
1572            },
1573            {
1574              "type": "number",
1575              "value": 4
1576            },
1577            {
1578              "type": "ref",
1579              "value": [
1580                {
1581                  "type": "var",
1582                  "value": "data"
1583                },
1584                {
1585                  "type": "string",
1586                  "value": "reports"
1587                },
1588                {
1589                  "type": "var",
1590                  "value": "i1"
1591                },
1592                {
1593                  "type": "string",
1594                  "value": "clearance_level"
1595                }
1596              ]
1597            }
1598          ]
1599        }
1600      ]
1601    ]
1602  }
1603}
1604```
1605
1606#### Unconditional Results from Partial Evaluation
1607
1608When you partially evaluate a query with the Compile API, OPA returns a new set of queries and supporting policies. However, in some cases, the result of Partial Evaluation is a conclusive, unconditional answer.
1609
1610For example, if you extend to policy above to include a "break glass" condition, the decision may be to allow all requests regardless of clearance level.
1611
1612```live:compile_unconditional_example:module:read_only
1613package example
1614
1615allow {
1616  input.subject.clearance_level >= data.reports[_].clearance_level
1617}
1618
1619allow {
1620  data.break_glass = true
1621}
1622```
1623
1624In this case, if `data.break_glass` is `true` then the query
1625`data.example.allow == true` will _always_ be true. If the query is
1626always true, the `"queries"` value in the result will contain an empty
1627array. The empty array indicates that your query can be satisfied
1628without any further evaluation.
1629
1630```http
1631HTTP/1.1 200 OK
1632Content-Type: application/json
1633```
1634
1635```json
1636{
1637  "result": {
1638    "queries": [
1639      [],
1640      [
1641        {
1642          "index": 0,
1643          "terms": [
1644            {
1645              "type": "ref",
1646              "value": [
1647                {
1648                  "type": "var",
1649                  "value": "gte"
1650                }
1651              ]
1652            },
1653            {
1654              "type": "number",
1655              "value": 4
1656            },
1657            {
1658              "type": "ref",
1659              "value": [
1660                {
1661                  "type": "var",
1662                  "value": "data"
1663                },
1664                {
1665                  "type": "string",
1666                  "value": "reports"
1667                },
1668                {
1669                  "type": "var",
1670                  "value": "$02"
1671                },
1672                {
1673                  "type": "string",
1674                  "value": "clearance_level"
1675                }
1676              ]
1677            }
1678          ]
1679        }
1680      ]
1681    ]
1682  }
1683}
1684
1685```
1686
1687It is also possible for queries to _never_ be true. For example, the
1688original policy could be extended to require that users be granted an
1689exception:
1690
1691```live:compile_unconditional_false_example:module:read_only
1692package example
1693
1694allow {
1695  input.subject.clearance_level >= data.reports[_].clearance_level
1696  exceptions[input.subject.name]
1697}
1698
1699exceptions["bob"]
1700exceptions["alice"]
1701```
1702
1703In this case, if we execute query on behalf of a user that does not
1704have an exception (e.g., `"eve"`), the OPA response will not contain a
1705`queries` field at all. This indicates there are NO conditions that
1706could make the query true.
1707
1708```http
1709HTTP/1.1 200 OK
1710Content-Type: application/json
1711```
1712
1713```json
1714{
1715  "result": {}
1716}
1717```
1718
1719The following table summarizes the behavior for partial evaluation results.
1720
1721| Example Query | Unknowns | Result | Description |
1722| --- | --- | --- | ---
1723| `input.x > 0` | `["input"]` | `{"result": {"queries": [[input.x > 0]]}}` | The query is partially evaluated and remaining conditions are returned. |
1724| `input.x > 0` | Not specified. | `{"result": {"queries": [[input.x > 0]]}}` | If the set of unknowns is not specified, it defaults to `["input"]`. |
1725| `input.x > 0` | `[]` | `{"result": {}}` | The query is false/undefined because there are no unknowns. |
1726| `1 > 0` | N/A | `{"result": {"queries": [[]]}}` | The query is always true. |
1727| `1 < 0` | N/A | `{"result": {}}` | The query is always false. |
1728
1729> The partially evaluated queries are represented as strings in the table above. The actual API response contains the JSON AST representation.
1730
1731## Authentication
1732
1733The API is secured via [HTTPS, Authentication, and Authorization](../security).
1734
1735###  Bearer Tokens
1736
1737When OPA is started with the ``--authentication=token`` command line flag,
1738clients MUST provide a Bearer token in the HTTP Authorization header:
1739
1740```http
1741GET /v1/data/exempli-gratia HTTP/1.1
1742Authorization: Bearer my-secret-token
1743```
1744
1745Bearer tokens must be represented with a valid HTTP header value character
1746sequence.
1747
1748OPA will extract the Bearer token value (which is set to ``my-secret-token``
1749above) and provide it to the authorization component inside OPA that will (i)
1750validate the token and (ii) execute the authorization policy configured by the
1751admin.
1752
1753## Errors
1754
1755All of the API endpoints use standard HTTP status codes to indicate success or
1756failure of an API call. If an API call fails, the response will contain a JSON
1757encoded object that provides more detail. The `errors` and `location` fields are
1758optional:
1759
1760```
1761{
1762  "code": "invalid_parameter",
1763  "message": "error(s) occurred while compiling module(s)",
1764  "errors": [
1765    {
1766      "code": "rego_unsafe_var_error",
1767      "message": "var x is unsafe",
1768      "location": {
1769        "file": "example",
1770        "row": 3,
1771        "col": 1
1772      }
1773    }
1774  ]
1775}
1776```
1777
1778### Method not Allowed
1779
1780OPA will respond with a 405 Error (Method Not Allowed) if the method used to access the URL is not supported. For example, if a client uses the *HEAD* method to access any path within "/v1/data/{path:.*}", a 405 will be returned.
1781
1782## Explanations
1783
1784OPA supports query explanations that describe (in detail) the steps taken to
1785produce query results.
1786
1787Explanations can be requested for:
1788
1789- [Data API](#data-api) GET queries
1790- [Query API](#query-api) queries
1791
1792Explanations are requested by setting the `explain` query parameter to one of
1793the following values:
1794
1795- **full** - returns a full query trace containing every step in the query evaluation process.
1796
1797By default, explanations are represented in a machine-friendly format. Set the
1798`pretty` parameter to request a human-friendly format for debugging purposes.
1799
1800### Trace Events
1801
1802When the `explain` query parameter is set to **full** , the response contains an array of Trace Event objects.
1803
1804Trace Event objects contain the following fields:
1805
1806- **op** - identifies the kind of Trace Event. Values: **"Enter"**, **"Exit"**, **"Eval"**, **"Fail"**, **"Redo"**.
1807- **query_id** - uniquely identifies the query that the Trace Event was emitted for.
1808- **parent_id** - identifies the parent query.
1809- **type** - indicates the type of the **node** field. Values: **"expr"**, **"rule"**, **"body"**.
1810- **node** - contains the AST element associated with the evaluation step.
1811- **locals** - contains the term bindings from the query at the time when the Trace Event was emitted.
1812
1813#### Query IDs
1814
1815Queries often reference rules or contain comprehensions. In both cases, query
1816evaluation involves evaluation of one or more other queries, e.g., the body of
1817the rule or comprehension.
1818
1819Trace Events from different queries can be distinguished by the **query_id**
1820field.
1821
1822Trace Events from related queries can be identified by the **parent_id** field.
1823
1824For example, if query A references a rule R, Trace Events emitted as part of
1825evaluating rule R's body will have the **parent_id** field set to query A's
1826**query_id**.
1827
1828#### Types of Events
1829
1830Each Trace Event represents a step in the query evaluation process. Trace Events
1831are emitted at the following points:
1832
1833- **enter** - before a body or rule is evaluated.
1834- **exit** - after a body or rule has evaluated successfully.
1835- **eval** - before an expression is evaluated.
1836- **fail** - after an expression has evaluated to false.
1837- **redo** - before evaluation restarts from a body, rule, or expression.
1838
1839By default, OPA searches for all sets of term bindings that make all expressions
1840in the query evaluate to true. Because there may be multiple answers, the search
1841can *restart* when OPA determines the query is true or false. When the search
1842restarts, a **Redo** Trace Event is emitted.
1843
1844#### Example Trace Event
1845
1846```json
1847{
1848  "op": "eval",
1849  "query_id": 20,
1850  "parent_id": 0,
1851  "type": "expr",
1852  "node": {
1853    "index": 1,
1854    "terms": [
1855      {
1856        "type": "var",
1857        "value": "eq"
1858      },
1859      {
1860        "type": "var",
1861        "value": "x"
1862      },
1863      {
1864        "type": "var",
1865        "value": "y"
1866      }
1867    ]
1868  },
1869  "locals": [
1870    {
1871      "key": {
1872        "type": "var",
1873        "value": "x"
1874      },
1875      "value": {
1876        "type": "string",
1877        "value": "hello"
1878      }
1879    }
1880  ]
1881}
1882```
1883
1884## Performance Metrics
1885
1886OPA can report detailed performance metrics at runtime. Performance metrics can
1887be requested on individual API calls and are returned inline with the API
1888response. To enable performance metric collection on an API call, specify the
1889`metrics=true` query parameter when executing the API call. Performance metrics
1890are currently supported for the following APIs:
1891
1892- Data API (GET and POST)
1893- Policy API (all methods)
1894- Query API (all methods)
1895
1896For example:
1897
1898```http
1899POST /v1/data/example?metrics=true HTTP/1.1
1900```
1901
1902Response:
1903
1904```http
1905HTTP/1.1 200 OK
1906Content-Type: application/json
1907```
1908
1909```json
1910{
1911  "metrics": {
1912    "timer_rego_query_compile_ns": 69994,
1913    "timer_rego_query_eval_ns": 48425,
1914    "timer_rego_query_parse_ns": 4096
1915  },
1916  "result": {
1917    "some_strings": [
1918      "hello",
1919      "world"
1920    ]
1921  }
1922}
1923```
1924
1925OPA currently supports the following query performance metrics:
1926
1927- **timer_rego_input_parse_ns**: time taken (in nanoseconds) to parse the input
1928- **timer_rego_query_parse_ns**: time taken (in nanonseconds) to parse the query.
1929- **timer_rego_query_compile_ns**: time taken (in nanonseconds) to compile the query.
1930- **timer_rego_query_eval_ns**: time taken (in nanonseconds) to evaluate the query.
1931- **timer_rego_module_parse_ns**: time taken (in nanoseconds) to parse the input policy module.
1932- **timer_rego_module_compile_ns**: time taken (in nanoseconds) to compile the loaded policy modules.
1933- **timer_server_handler_ns**: time take (in nanoseconds) to handle the API request.
1934
1935OPA also supports query instrumentation. To enable query instrumentation,
1936specify the `instrument=true` query parameter when executing the API call.
1937Query instrumentation can help diagnose performance problems, however, it can
1938add significant overhead to query evaluation. We recommend leaving query
1939instrumentation off unless you are debugging a performance problem.
1940
1941When instrumentation is enabled there are several additional performance metrics
1942for the compilation stages. They follow the format of `timer_compile_stage_*_ns`
1943and `timer_query_compile_stage_*_ns` for the query and module compilation stages.
1944
1945## Provenance
1946
1947OPA can report provenance information at runtime. Provenance information can
1948be requested on individual API calls and are returned inline with the API
1949response. To obtain provenance information on an API call, specify the
1950`provenance=true` query parameter when executing the API call. Provenance information
1951is currently supported for the following APIs:
1952
1953- Data API (GET and POST)
1954
1955For example:
1956
1957```http
1958POST /v1/data/example?provenance=true HTTP/1.1
1959```
1960
1961Response:
1962
1963```http
1964HTTP/1.1 200 OK
1965Content-Type: application/json
1966```
1967
1968```json
1969{
1970  "provenance": {
1971    "build_commit": "1955fc4d",
1972    "build_host": "foo.com",
1973    "build_timestamp": "2019-04-29T23:42:04Z",
1974    "bundles": {
1975      "authz": {
1976        "revision": "ID-b1298a6c-6ad8-11e9-a26f-d38b5ceadad5"
1977      }
1978    },
1979    "version": "0.10.8-dev"
1980  },
1981  "result": true
1982}
1983```
1984
1985OPA currently supports the following query provenance information:
1986
1987- **version**: The version of this OPA instance.
1988- **build_commit**: The git commit id of this OPA build.
1989- **build_timestamp**: The timestamp when this instance was built.
1990- **build_host**: The hostname where this instance was built.
1991- **revision**: (Deprecated) The _revision_ string included in a .manifest file (if present) within
1992  a bundle. Omitted when `bundles` are configured.
1993- **bundles**: A set of key-value pairs describing each bundle activated on the server. Includes
1994  the `revision` field which is the _revision_ string included in a .manifest file (if present)
1995  within a bundle
1996
1997## Watches
1998
1999OPA can set watches on queries and report whenever the result of evaluating the query has changed. When a watch is set on a query, the requesting connection will be maintained as the query results are streamed back in HTTP Chunked Encoding format. A notification reflecting a certain change to the query results will be delivered _at most once_. That is, if a watch is set on `data.x`, and then multiple writes are made to `data.x`, say `1`, `2` and `3`, only the notification reflecting `data.x=3` is always seen eventually (assuming the watch is not ended, there are no connection problems, etc). The notifications reflecting `data.x=1` and `data.x=2` _might_ be seen. However, the notifications sent are guaranteed to be in order (`data.x=2` will always come after `data.x=1`, if it comes).
2000
2001The notification stream will not be delimited by any value; the client is expected to be able to parse JSON values from the stream one by one, recognizing where one ends and the next begins.
2002
2003The notification stream is a stream of JSON objects, each of which has the following structure:
2004```
2005{
2006    "result": <result>,
2007    "error": <error>,
2008    "metrics": <metrics>,
2009    "explanation": <explanation>,
2010}
2011```
2012
2013The `error` field is optional; it is omitted when no errors occur. If it is present, it is an [Error](#errors) describing any errors encountered while evaluating the query the watch was set on. If the policies on the server are changed such that the query no longer compiles, the contents of the error's `message` field will start with the text "watch invalidated:" and will be followed with the reason for invalidation. The watch will be ended by the server and the stream closed.
2014
2015The `metrics` field represents [Performance Metrics](#performance-metrics) for the evaluation of the query. It will only be present if metrics were requested in the API call that started the watch.
2016
2017The `explanation` field represents an [Explanation](#explanations) of how the query answer was found. It will only be present if explanations were requested in the API call that started the watch.
2018
2019If there are no errors, the `result` field will be a JSON array of the results of evaluating the query. The format of a result is:
2020```
2021{
2022    "expressions": [
2023        {
2024            "value": true,
2025            "text": "a = data.x",
2026            "location":{"row":1,"col":1}
2027        },
2028        ...
2029    ],
2030    "bindings": {...}
2031}
2032```
2033
2034The `expressions` field is an array of the results of evaluating each of the expressions in the query. `value` is the expression's value, `text` is the actual expression, and `location` describes the location of the expression within the query. The values above are examples.
2035
2036The `bindings` field is a JSON object mapping `string`s to JSON values that describe the variable bindings resulting from evaluating the query.
2037
2038If the watch was set on a data reference instead of a query, the `result` field will simply be the value of the document requested, instead of an array of values.
2039
2040
2041## Health API
2042
2043The `/health` API endpoint executes a simple built-in policy query to verify
2044that the server is operational. Optionally it can account for bundle activation as well
2045(useful for "ready" checks at startup).
2046
2047#### Query Parameters
2048`bundles` - Boolean parameter to account for bundle activation status in response. This includes
2049            any discovery bundles or bundles defined in the loaded discovery configuration.
2050`plugins` - Boolean parameter to account for plugin status in response.
2051
2052#### Status Codes
2053- **200** - OPA service is healthy. If the `bundles` option is specified then all configured bundles have
2054            been activated. If the `plugins` option is specified then all plugins are in an OK state.
2055- **500** - OPA service is not healthy. If the `bundles` option is specified this can mean any of the configured
2056            bundles have not yet been activated. If the `plugins` option is specified then at least one
2057            plugin is in a non-OK state.
2058
2059> *Note*: The bundle activation check is only for initial bundle activation. Subsequent downloads
2060  will not affect the health check. The [Status](../management/#status)
2061  API should be used for more fine-grained bundle status monitoring.
2062
2063#### Example Request
2064```http
2065GET /health HTTP/1.1
2066```
2067
2068#### Example Request (bundle activation)
2069```http
2070GET /health?bundles HTTP/1.1
2071```
2072
2073#### Example Request (plugin status)
2074```http
2075GET /health?plugins HTTP/1.1
2076```
2077
2078#### Healthy Response
2079```http
2080HTTP/1.1 200 OK
2081Content-Type: application/json
2082```
2083```json
2084{}
2085```
2086
2087#### Unhealthy Response
2088```http
2089HTTP/1.1 500 Internal Server Error
2090Content-Type: application/json
2091```
2092```json
2093{}
2094```
2095