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