]> granicus.if.org Git - icinga2/blob - doc/12-icinga2-api.md
Docs: Update API and Library Reference chapters
[icinga2] / doc / 12-icinga2-api.md
1 # <a id="icinga2-api"></a> Icinga 2 API
2
3 ## <a id="icinga2-api-setup"></a> Setting up the API
4
5 You can run the CLI command `icinga2 api setup` to enable the
6 `api` [feature](11-cli-commands.md#enable-features) and set up
7 certificates as well as a new API user `root` with an auto-generated password in the
8 `/etc/icinga2/conf.d/api-users.conf` configuration file:
9
10     # icinga2 api setup
11
12 Make sure to restart Icinga 2 to enable the changes you just made:
13
14     # service icinga2 restart
15
16 If you prefer to set up the API manually, you will have to perform the following steps:
17
18 * Set up X.509 certificates for Icinga 2
19 * Enable the `api` feature (`icinga2 feature enable api`)
20 * Create an `ApiUser` object for authentication
21
22 The next chapter provides a quick overview of how you can use the API.
23
24 ## <a id="icinga2-api-introduction"></a> Introduction
25
26 The Icinga 2 API allows you to manage configuration objects
27 and resources in a simple, programmatic way using HTTP requests.
28
29 The URL endpoints are logically separated allowing you to easily
30 make calls to
31
32 * query, create, modify and delete [config objects](12-icinga2-api.md#icinga2-api-config-objects)
33 * perform [actions](12-icinga2-api.md#icinga2-api-actions) (reschedule checks, etc.)
34 * subscribe to [event streams](12-icinga2-api.md#icinga2-api-event-streams)
35 * [manage configuration packages](12-icinga2-api.md#icinga2-api-config-management)
36 * evaluate [script expressions](12-icinga2-api.md#icinga2-api-console)
37
38 ### <a id="icinga2-api-requests"></a> Requests
39
40 Any tool capable of making HTTP requests can communicate with
41 the API, for example [curl](http://curl.haxx.se).
42
43 Requests are only allowed to use the HTTPS protocol so that
44 traffic remains encrypted.
45
46 By default the Icinga 2 API listens on port `5665` which is shared with
47 the cluster stack. The port can be changed by setting the `bind_port` attribute
48 for the [ApiListener](9-object-types.md#objecttype-apilistener)
49 object in the `/etc/icinga2/features-available/api.conf`
50 configuration file.
51
52 Supported request methods:
53
54   Method | Usage
55   -------|--------
56   GET    | Retrieve information about configuration objects. Any request using the GET method is read-only and does not affect any objects.
57   POST   | Update attributes of a specified configuration object.
58   PUT    | Create a new object. The PUT request must include all attributes required to create a new object.
59   DELETE | Remove an object created by the API. The DELETE method is idempotent and does not require any check if the object actually exists.
60
61 All requests apart from `GET` require that the following `Accept` header is set:
62
63     Accept: application/json
64
65 Each URL is prefixed with the API version (currently "/v1").
66
67 ### <a id="icinga2-api-responses"></a> Responses
68
69 Successful requests will send back a response body containing a `results`
70 list. Depending on the number of affected objects in your request, the
71 `results` list may contain more than one entry.
72
73 The output will be sent back as a JSON object:
74
75
76     {
77         "results": [
78             {
79                 "code": 200.0,
80                 "status": "Object was created."
81             }
82         ]
83     }
84
85 Tip: If you are working on the CLI with curl you can also use [jq](https://stedolan.github.io/jq/)
86 to format the returned JSON output in a readable manner. The documentation
87 prefers `python -m json.tool` as Python is available nearly everywhere.
88
89 > **Note**
90 >
91 > Future versions of Icinga 2 might set additional fields. Your application
92 > should gracefully handle fields it is not familiar with, for example by
93 > ignoring them.
94
95 ### <a id="icinga2-api-http-statuses"></a> HTTP Statuses
96
97 The API will return standard [HTTP statuses](https://www.ietf.org/rfc/rfc2616.txt)
98 including error codes.
99
100 When an error occurs, the response body will contain additional information
101 about the problem and its source.
102
103 A status code between 200 and 299 generally means that the request was
104 successful.
105
106 Return codes within the 400 range indicate that there was a problem with the
107 request. Either you did not authenticate correctly, you are missing the authorization
108 for your requested action, the requested object does not exist or the request
109 was malformed.
110
111 A status in the range of 500 generally means that there was a server-side problem
112 and Icinga 2 is unable to process your request.
113
114 ### <a id="icinga2-api-authentication"></a> Authentication
115
116 There are two different ways for authenticating against the Icinga 2 API:
117
118 * username and password using HTTP basic auth
119 * X.509 certificate
120
121 In order to configure a new API user you'll need to add a new [ApiUser](9-object-types.md#objecttype-apiuser)
122 configuration object. In this example `root` will be the basic auth username
123 and the `password` attribute contains the basic auth password.
124
125     # vim /etc/icinga2/conf.d/api-users.conf
126
127     object ApiUser "root" {
128       password = "icinga"
129     }
130
131 Alternatively you can use X.509 client certificates by specifying the `client_cn`
132 the API should trust. The X.509 certificate has to be signed by the CA certificate
133 that is configured in the [ApiListener](9-object-types.md#objecttype-apilistener) object.
134
135     # vim /etc/icinga2/conf.d/api-users.conf
136
137     object ApiUser "root" {
138       client_cn = "CertificateCommonName"
139     }
140
141 An `ApiUser` object can have both authentication methods configured.
142
143 You can test authentication by sending a GET request to the API:
144
145     $ curl -k -s -u root:icinga 'https://localhost:5665/v1'
146
147 In case you get an error message make sure to check the API user credentials.
148
149 When using client certificates for authentication you'll need to pass your client certificate
150 and private key to the curl call:
151
152     $ curl -k --cert example.localdomain.crt --key example.localdomain.key 'https://example.localdomain:5665/v1/status'
153
154 In case of an error make sure to verify the client certificate and CA.
155
156 The curl parameter `-k` disables certificate verification and should therefore
157 only be used for testing. In order to securely check each connection you'll need to
158 specify the trusted CA certificate using the curl parameter`--cacert`:
159
160     $ curl -u root:icinga --cacert ca.crt 'icinga2.node1.localdomain:5665/v1'
161
162 Read the next chapter on [API permissions](12-icinga2-api.md#icinga2-api-permissions)
163 in order to configure authorization settings for your newly created API user.
164
165 ### <a id="icinga2-api-permissions"></a> Permissions
166
167 By default an API user does not have any permissions to perform
168 actions on the URL endpoints.
169
170 Permissions for API users must be specified in the `permissions` attribute
171 as array. The array items can be a list of permission strings with wildcard
172 matches.
173
174 Example for an API user with all permissions:
175
176     permissions = [ "*" ]
177
178 Note that you can use wildcards. Here's another example that only allows the user
179 to perform read-only object queries for hosts and services:
180
181     permissions = [ "objects/query/Host", "objects/query/Service" ]
182
183 You can also further restrict permissions by specifying a filter expression. The
184 filter expression has to be a [lambda function](17-language-reference.md#nullary-lambdas)
185 which must return a boolean value.
186
187 The following example allows the API user to query all hosts and services which have a
188 custom attribute `os` that matches the regular expression `^Linux`.
189 The [regex function](18-library-reference.md#global-functions-regex) is available as global function.
190
191     permissions = [
192       {
193         permission = "objects/query/Host"
194         filter = {{ regex("^Linux", host.vars.os) }}
195       },
196       {
197         permission = "objects/query/Service"
198         filter = {{ regex("^Linux", service.vars.os) }}
199       }
200     ]
201
202 More information about filters can be found in the [filters](12-icinga2-api.md#icinga2-api-filters) chapter.
203
204 Available permissions for specific URL endpoints:
205
206   Permissions                   | URL Endpoint  | Supports Filters
207   ------------------------------|---------------|-----------------
208   actions/&lt;action&gt;        | /v1/actions   | Yes
209   config/query                  | /v1/config    | No
210   config/modify                 | /v1/config    | No
211   console                       | /v1/console   | No
212   events/&lt;type&gt;           | /v1/events    | No
213   objects/query/&lt;type&gt;    | /v1/objects   | Yes
214   objects/create/&lt;type&gt;   | /v1/objects   | No
215   objects/modify/&lt;type&gt;   | /v1/objects   | Yes
216   objects/delete/&lt;type&gt;   | /v1/objects   | Yes
217   status/query                  | /v1/status    | Yes
218   templates/&lt;type&gt;        | /v1/templates | Yes
219   types                         | /v1/types     | Yes
220   variables                     | /v1/variables | Yes
221
222 The required actions or types can be replaced by using a wildcard match ("\*").
223
224 ### <a id="icinga2-api-parameters"></a> Parameters
225
226 Depending on the request method there are two ways of
227 passing parameters to the request:
228
229 * JSON object as request body (all request methods other than `GET`)
230 * Query string as URL parameter (all request methods)
231
232 Reserved characters by the HTTP protocol must be [URL-encoded](https://en.wikipedia.org/wiki/Percent-encoding)
233 as query string, e.g. a space character becomes `%20`.
234
235 Example for a URL-encoded query string:
236
237     /v1/objects/hosts?filter=match(%22example.localdomain*%22,host.name)&attrs=name&attrs=state
238
239 Here are the exact same query parameters as a JSON object:
240
241     { "filter": "match(\"example.localdomain*\",host.name)", "attrs": [ "host.name", "host.state" ] }
242
243 The [match function](18-library-reference.md#global-functions-match) is available as global function
244 in Icinga 2.
245
246 ### <a id="icinga2-api-requests-method-override"></a> Request Method Override
247
248 `GET` requests do not allow you to send a request body. In case you cannot pass everything as URL parameters (e.g. complex filters or JSON-encoded dictionaries) you can use the `X-HTTP-Method-Override` header. This comes in handy when you are using HTTP proxies disallowing `PUT` or `DELETE` requests too.
249
250 Query an existing object by sending a `POST` request with `X-HTTP-Method-Override: GET` as request header:
251
252     $ curl -k -s -u 'root:icinga' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/hosts'
253
254 Delete an existing object by sending a `POST` request with `X-HTTP-Method-Override: DELETE` as request header:
255
256     $ curl -k -s -u 'root:icinga' -H 'X-HTTP-Method-Override: DELETE' -X POST 'https://localhost:5665/v1/objects/hosts/example.localdomain'
257
258 ### <a id="icinga2-api-filters"></a> Filters
259
260 #### <a id="icinga2-api-simple-filters"></a> Simple Filters
261
262 By default actions and queries operate on all objects unless further restricted by the user. For
263 example, the following query returns all `Host` objects:
264
265     https://localhost:5665/v1/objects/hosts
266
267 If you're only interested in a single object, you can limit the output to that object by specifying its name:
268
269     https://localhost:5665/v1/objects/hosts?host=localhost
270
271 **The name of the URL parameter is the lower-case version of the type the query applies to.** For
272 example, for `Host` objects the URL parameter therefore is `host`, for `Service` objects it is
273 `service` and so on.
274
275 You can also specify multiple objects:
276
277     https://localhost:5665/v1/objects/hosts?hosts=first-host&hosts=second-host
278
279 Again -- like in the previous example -- the name of the URL parameter is the lower-case version of the type. However, because we're specifying multiple objects here the **plural form** of the type is used.
280
281 When specifying names for objects which have composite names like for example services the
282 full name has to be used:
283
284     https://localhost:5665/v1/objects/services?service=localhost!ping6
285
286 The full name of an object can be obtained by looking at the `__name` attribute.
287
288 #### <a id="icinga2-api-advanced-filters"></a> Advanced Filters
289
290 Most of the information provided in this chapter applies to both permission filters (as used when
291 configuring `ApiUser` objects) and filters specified in queries.
292
293 Advanced filters allow users to filter objects using lambda expressions. The syntax for these filters is the same like for [apply rule expressions](3-monitoring-basics.md#using-apply-expressions).
294
295 > **Note**
296 >
297 > Filters used as URL parameter must be URL-encoded. The following examples
298 > are **not URL-encoded** for better readability.
299
300 Example matching all services in NOT-OK state:
301
302     https://localhost:5665/v1/objects/services?filter=service.state!=ServiceOK
303
304 Example [matching](18-library-reference.md#global-functions-match) all hosts by a name string pattern:
305
306     https://localhost:5665/v1/objects/hosts?filter=match("example.localdomain*",host.name)
307
308 Example for all hosts which are in the host group `linux-servers`:
309
310     https://localhost:5665/v1/objects/hosts?filter="linux-servers" in host.groups
311
312 User-specified filters are run in a sandbox environment which ensures that filters cannot
313 modify Icinga's state, for example object attributes or global variables.
314
315 When querying objects of a specific type the filter expression is evaluated for each object
316 of that type. The object is made available to the filter expression as a variable whose name
317 is the lower-case version of the object's type name.
318
319 For example when querying objects of type `Host` the variable in the filter expression is named
320 `host`. Additionally related objects such as the host's check command are also made available
321 (e.g., via the `check_command` variable). The variable names are the exact same as for the `joins`
322 query parameter; see [object query joins](12-icinga2-api.md#icinga2-api-config-objects-query-joins)
323 for details.
324
325 The object is also made available via the `obj` variable. This makes it easier to build
326 filters which can be used for more than one object type (e.g., for permissions).
327
328 Some queries can be performed for more than just one object type. One example is the 'reschedule-check'
329 action which can be used for both hosts and services. When using advanced filters you will also have to specify the
330 type using the `type` parameter:
331
332     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \
333     -d '{ "type": "Service", "filter": "service.name==\"ping6\"" }' | python -m json.tool
334
335 When building filters you have to ensure that values such as
336 `"linux-servers"` are escaped properly according to the rules of the Icinga 2 configuration
337 language.
338
339 To make using the API in scripts easier you can use the `filter_vars` attribute to specify
340 variables which should be made available to your filter expression. This way you don't have
341 to worry about escaping values:
342
343     $ curl -k -s -u 'root:icinga' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/hosts' \
344     -d '{ "filter": "host.vars.os == os", "filter_vars": { "os": "Linux" } }'
345
346 We're using X-HTTP-Method-Override here because the HTTP specification does
347 not allow message bodies for GET requests.
348
349 The `filters_vars` attribute can only be used inside the request body, but not as
350 a URL parameter because there is no way to specify a dictionary in a URL.
351
352 ## <a id="icinga2-api-config-objects"></a> Config Objects
353
354 Provides methods to manage configuration objects:
355
356 * [creating objects](12-icinga2-api.md#icinga2-api-config-objects-create)
357 * [querying objects](12-icinga2-api.md#icinga2-api-config-objects-query)
358 * [modifying objects](12-icinga2-api.md#icinga2-api-config-objects-modify)
359 * [deleting objects](12-icinga2-api.md#icinga2-api-config-objects-delete)
360
361 ### <a id="icinga2-api-config-objects-cluster-sync"></a> API Objects and Cluster Config Sync
362
363 Newly created or updated objects can be synced throughout your
364 Icinga 2 cluster. Set the `zone` attribute to the zone this object
365 belongs to and let the API and cluster handle the rest.
366
367 Objects without a zone attribute are only synced in the same zone the Icinga instance belongs to.
368
369 > **Note**
370 >
371 > Cluster nodes must accept configuration for creating, modifying
372 > and deleting objects. Ensure that `accept_config` is set to `true`
373 > in the [ApiListener](9-object-types.md#objecttype-apilistener) object
374 > on each node.
375
376 If you add a new cluster instance, or reconnect an instance which has been offline
377 for a while, Icinga 2 takes care of the initial object sync for all objects
378 created by the API.
379
380 ### <a id="icinga2-api-config-objects-query"></a> Querying Objects
381
382 You can request information about configuration objects by sending
383 a `GET` query to the `/v1/objects/<type>` URL endpoint. `<type` has
384 to be replaced with the plural name of the object type you are interested
385 in:
386
387     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts'
388
389 A list of all available configuration types is available in the
390 [object types](9-object-types.md#object-types) chapter.
391
392 The following URL parameters are available:
393
394   Parameters | Type         | Description
395   -----------|--------------|----------------------------
396   attrs      | string array | **Optional.** Limits attributes in the output.
397   joins      | string array | **Optional.** Join related object types and their attributes (`?joins=host` for the entire set, or selectively by `?joins=host.name`).
398   meta       | string array | **Optional.** Enable meta information using `?meta=used_by` (references from other objects) and/or `?meta=location` (location information). Defaults to disabled.
399
400 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) may be provided.
401
402 Instead of using a filter you can optionally specify the object name in the
403 URL path when querying a single object. For objects with composite names
404 (e.g. services) the full name (e.g. `localhost!http`) must be specified:
405
406     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services/localhost!http'
407
408 You can limit the output to specific attributes using the `attrs` URL parameter:
409
410     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts/example.localdomain?attrs=name&attrs=address' | python -m json.tool
411     {
412         "results": [
413             {
414                 "attrs": {
415                     "name": "example.localdomain"
416                     "address": "192.168.1.1"
417                 },
418                 "joins": {},
419                 "meta": {},
420                 "name": "example.localdomain",
421                 "type": "Host"
422             }
423         ]
424     }
425
426 #### <a id="icinga2-api-config-objects-query-result"></a> Object Queries Result
427
428 Each response entry in the results array contains the following attributes:
429
430   Attribute  | Type       | Description
431   -----------|------------|--------------
432   name       | string     | Full object name.
433   type       | string     | Object type.
434   attrs      | dictionary | Object attributes (can be filtered using the URL parameter `attrs`).
435   joins      | dictionary | [Joined object types](12-icinga2-api.md#icinga2-api-config-objects-query-joins) as key, attributes as nested dictionary. Disabled by default.
436   meta       | dictionary | Contains `used_by` object references. Disabled by default, enable it using `?meta=used_by` as URL parameter.
437
438 #### <a id="icinga2-api-config-objects-query-joins"></a> Object Query Joins
439
440 Icinga 2 knows about object relations. For example it can optionally return
441 information about the host when querying service objects.
442
443 The following query retrieves all host attributes:
444
445     https://localhost:5665/v1/objects/services?joins=host
446
447 Instead of requesting all host attributes you can also limit the output to specific
448 attributes:
449
450     https://localhost:5665/v1/objects/services?joins=host.name&joins=host.address
451
452 You can request that all available joins are returned in the result set by using
453 the `all_joins` query parameter.
454
455     https://localhost:5665/v1/objects/services?all_joins=1
456
457 > **Note**
458 >
459 > For performance reasons you should only request attributes which your application
460 > requires.
461
462 The following joins are available:
463
464   Object Type  | Object Relations (`joins` prefix name)
465   -------------|------------------------------------------
466   Service      | host, check\_command, check\_period, event\_command, command\_endpoint
467   Host         | check\_command, check\_period, event\_command, command\_endpoint
468   Notification | host, service, command, period
469   Dependency   | child\_host, child\_service, parent\_host, parent\_service, period
470   User         | period
471   Zones        | parent
472
473 Here's an example that retrieves all service objects for hosts which have had their `os`
474 custom attribute set to `Linux`. The result set contains the `display_name` and `check_command`
475 attributes for the service. The query also returns the host's `name` and `address` attribute
476 via a join:
477
478     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services?attrs=display_name&attrs=check_command&joins=host.name&joins=host.address&filter=host.vars.os==%22Linux%22' | python -m json.tool
479
480     {
481         "results": [
482             {
483                 "attrs": {
484                     "check_command": "ping4",
485                     "display_name": "ping4"
486                 },
487                 "joins": {
488                     "host": {
489                         "address": "192.168.1.1",
490                         "name": "example.localdomain"
491                     }
492                 },
493                 "meta": {},
494                 "name": "example.localdomain!ping4",
495                 "type": "Service"
496             },
497             {
498                 "attrs": {
499                     "check_command": "ssh",
500                     "display_name": "ssh"
501                 },
502                 "joins": {
503                     "host": {
504                         "address": "192.168.1.1",
505                         "name": "example.localdomain"
506                     }
507                 },
508                 "meta": {},
509                 "name": "example.localdomain!ssh",
510                 "type": "Service"
511             }
512         ]
513     }
514
515 In case you want to fetch all [comments](9-object-types.md#objecttype-comment)
516 for hosts and services, you can use the following query URL (similar example
517 for downtimes):
518
519    https://localhost:5665/v1/objects/comments?joins=host&joins=service
520
521 This is another example for listing all service objects which are unhandled problems (state is not OK
522 and no downtime or acknowledgement set):
523
524    $ curl -k -s -u root:icinga -H 'X-HTTP-Method-Override: GET' -X POST 'https://127.0.0.1:5665/v1/objects/services' \
525     -d '{ "joins": [ "host.name", "host.address" ], "attrs": [ "name", "state", "downtime_depth", "acknowledgement" ], "filter": "service.state != ServiceOK && service.downtime_depth == 0.0 && service.acknowledgement == 0.0" }' | python -m json.tool
526
527     {
528         "results": [
529             {
530                 "attrs": {
531                     "acknowledgement": 0.0,
532                     "downtime_depth": 0.0,
533                     "name": "10807-service",
534                     "state": 3.0
535                 },
536                 "joins": {
537                     "host": {
538                         "address": "",
539                         "name": "10807-host"
540                     }
541                 },
542                 "meta": {},
543                 "name": "10807-host!10807-service",
544                 "type": "Service"
545             }
546         ]
547     }
548
549
550 ### <a id="icinga2-api-config-objects-create"></a> Creating Config Objects
551
552 New objects must be created by sending a PUT request. The following
553 parameters need to be passed inside the JSON body:
554
555   Parameters | Type         | Description
556   -----------|--------------|--------------------------
557   templates  | string array | **Optional.** Import existing configuration templates for this object type. Note: These templates must either be statically configured or provided in [config packages](12-icinga2-api.md#icinga2-api-config-management)-
558   attrs      | dictionary   | **Required.** Set specific object attributes for this [object type](9-object-types.md#object-types).
559
560 The object name must be specified as part of the URL path. For objects with composite names (e.g. services)
561 the full name (e.g. `localhost!http`) must be specified.
562
563 If attributes are of the Dictionary type, you can also use the indexer format. This might be necessary to only override specific custom variables and keep all other existing custom variables (e.g. from templates):
564
565     "attrs": { "vars.os": "Linux" }
566
567 Example for creating the new host object `example.localdomain`:
568
569     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
570     -d '{ "templates": [ "generic-host" ], "attrs": { "address": "192.168.1.1", "check_command": "hostalive", "vars.os" : "Linux" } }' \
571     | python -m json.tool
572     {
573         "results": [
574             {
575                 "code": 200.0,
576                 "status": "Object was created."
577             }
578         ]
579     }
580
581 If the configuration validation fails, the new object will not be created and the response body
582 contains a detailed error message. The following example is missing the `check_command` attribute
583 which is required for host objects:
584
585     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
586     -d '{ "attrs": { "address": "192.168.1.1", "vars.os" : "Linux" } }' \
587     | python -m json.tool
588     {
589         "results": [
590             {
591                 "code": 500.0,
592                 "errors": [
593                     "Error: Validation failed for object 'example.localdomain' of type 'Host'; Attribute 'check_command': Attribute must not be empty."
594                 ],
595                 "status": "Object could not be created."
596             }
597         ]
598     }
599
600 Service objects must be created using their full name ("hostname!servicename") referencing an existing host object:
601
602     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/services/localhost!realtime-load' \
603     -d '{ "templates": [ "generic-service" ], "attrs": { "check_command": "load", "check_interval": 1,"retry_interval": 1 } }'
604
605
606 Example for a new CheckCommand object:
607
608     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/checkcommands/mytest' \
609     -d '{ "templates": [ "plugin-check-command" ], "attrs": { "command": [ "/usr/local/sbin/check_http" ], "arguments": { "-I": "$mytest_iparam$" } } }'
610
611
612 ### <a id="icinga2-api-config-objects-modify"></a> Modifying Objects
613
614 Existing objects must be modified by sending a `POST` request. The following
615 parameters need to be passed inside the JSON body:
616
617   Parameters | Type       | Description
618   -----------|------------|---------------------------
619   attrs      | dictionary | **Required.** Set specific object attributes for this [object type](9-object-types.md#object-types).
620
621 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) should be provided.
622
623 **Note**: Modified attributes do not trigger a re-evaluation of existing
624 static [apply rules](3-monitoring-basics.md#using-apply) and [group assignments](3-monitoring-basics.md#group-assign-intro).
625 Delete and re-create the objects if you require such changes.
626 Furthermore you cannot modify templates which have already been resolved
627 during [object creation](12-icinga2-api.md#icinga2-api-config-objects-create).
628
629
630 If attributes are of the Dictionary type, you can also use the indexer format:
631
632     "attrs": { "vars.os": "Linux" }
633
634 The following example updates the `address` attribute and the custom attribute `os` for the `example.localdomain` host:
635
636     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/hosts/example.localdomain' \
637     -d '{ "attrs": { "address": "192.168.1.2", "vars.os" : "Windows" } }' \
638     | python -m json.tool
639     {
640         "results": [
641             {
642                 "code": 200.0,
643                 "name": "example.localdomain",
644                 "status": "Attributes updated.",
645                 "type": "Host"
646             }
647         ]
648     }
649
650
651 ### <a id="icinga2-api-config-objects-delete"></a> Deleting Objects
652
653 You can delete objects created using the API by sending a `DELETE`
654 request.
655
656   Parameters | Type    | Description
657   -----------|---------|---------------
658   cascade    | boolean |  **Optional.** Delete objects depending on the deleted objects (e.g. services on a host).
659
660 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) should be provided.
661
662 Example for deleting the host object `example.localdomain`:
663
664     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE 'https://localhost:5665/v1/objects/hosts/example.localdomain?cascade=1' | python -m json.tool
665     {
666         "results": [
667             {
668                 "code": 200.0,
669                 "name": "example.localdomain",
670                 "status": "Object was deleted.",
671                 "type": "Host"
672             }
673         ]
674     }
675
676 ## <a id="icinga2-api-config-templates"></a> Config Templates
677
678 Provides methods to manage configuration templates:
679
680 * [querying templates](12-icinga2-api.md#icinga2-api-config-templates-query)
681
682 Creation, modification and deletion of templates at runtime is not supported.
683
684 ### <a id="icinga2-api-config-templates-query"></a> Querying Templates
685
686 You can request information about configuration templates by sending
687 a `GET` query to the `/v1/templates/<type>` URL endpoint. `<type` has
688 to be replaced with the plural name of the object type you are interested
689 in:
690
691     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/templates/hosts'
692
693 A list of all available configuration types is available in the
694 [object types](9-object-types.md#object-types) chapter.
695
696 A [filter](12-icinga2-api.md#icinga2-api-filters) may be provided for this query type. The
697 template object can be accessed in the filter using the `tmpl` variable. In this
698 example the [match function](18-library-reference.md#global-functions-match) is used to
699 check a wildcard string pattern against `tmpl.name`:
700
701     $ curl -k -s -u root:icinga 'https://localhost:5661/v1/templates/hosts' -H "Accept: application/json" -X PUT -H "X-HTTP-Method-Override: GET" \
702     -d '{ "filter": "match(\"g*\", tmpl.name)" }'
703
704 Instead of using a filter you can optionally specify the template name in the
705 URL path when querying a single object:
706
707     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/templates/hosts/generic-host'
708
709 The result set contains the type, name as well as the location of the template.
710
711 ## <a id="icinga2-api-variables"></a> Variables
712
713 Provides methods to manage global variables:
714
715 * [querying variables](12-icinga2-api.md#icinga2-api-variables-query)
716
717 ### <a id="icinga2-api-variables-query"></a> Querying Variables
718
719 You can request information about global variables by sending
720 a `GET` query to the `/v1/variables/` URL endpoint:
721
722     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/variables'
723
724 A [filter](12-icinga2-api.md#icinga2-api-filters) may be provided for this query type. The
725 variable information object can be accessed in the filter using the `variable` variable:
726
727     $ curl -u root:root -k 'https://localhost:5661/v1/variables' -H "Accept: application/json" -X PUT -H "X-HTTP-Method-Override: GET" \
728     -d '{ "filter": "variable.type in [ \"String\", \"Number\" ]" }'
729
730 Instead of using a filter you can optionally specify the variable name in the
731 URL path when querying a single variable:
732
733     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/variables/PrefixDir'
734
735 The result set contains the type, name and value of the global variable.
736
737 ## <a id="icinga2-api-actions"></a> Actions
738
739 There are several actions available for Icinga 2 provided by the `/v1/actions`
740 URL endpoint. You can run actions by sending a `POST` request.
741
742 In case you have been using the [external commands](14-features.md#external-commands)
743 in the past, the API actions provide a similar interface with filter
744 capabilities for some of the more common targets which do not directly change
745 the configuration.
746
747 All actions return a 200 `OK` or an appropriate error code for each
748 action performed on each object matching the supplied filter.
749
750 Actions which affect the Icinga Application itself such as disabling
751 notification on a program-wide basis must be applied by updating the
752 [IcingaApplication object](12-icinga2-api.md#icinga2-api-config-objects)
753 called `app`.
754
755     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/icingaapplications/app' -d '{ "attrs": { "enable_notifications": false } }'
756
757 ### <a id="icinga2-api-actions-process-check-result"></a> process-check-result
758
759 Process a check result for a host or a service.
760
761 Send a `POST` request to the URL endpoint `/v1/actions/process-check-result`.
762
763   Parameter         | Type         | Description
764   ------------------|--------------|--------------
765   exit\_status      | integer      | **Required.** For services: 0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN, for hosts: 0=OK, 1=CRITICAL.
766   plugin\_output    | string       | **Required.** The plugins main output. Does **not** contain the performance data.
767   performance\_data | string array | **Optional.** The performance data.
768   check\_command    | string array | **Optional.** The first entry should be the check commands path, then one entry for each command line option followed by an entry for each of its argument.
769   check\_source     | string       | **Optional.** Usually the name of the `command_endpoint`
770
771 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
772
773 Example:
774
775     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/process-check-result?service=example.localdomain!passive-ping6' \
776     -d '{ "exit_status": 2, "plugin_output": "PING CRITICAL - Packet loss = 100%", "performance_data": [ "rta=5000.000000ms;3000.000000;5000.000000;0.000000", "pl=100%;80;100;0" ], "check_source": "example.localdomain" }' | python -m json.tool
777
778     {
779         "results": [
780             {
781                 "code": 200.0,
782                 "status": "Successfully processed check result for object 'localdomain!passive-ping6'."
783             }
784         ]
785     }
786
787 ### <a id="icinga2-api-actions-reschedule-check"></a> reschedule-check
788
789 Reschedule a check for hosts and services. The check can be forced if required.
790
791 Send a `POST` request to the URL endpoint `/v1/actions/reschedule-check`.
792
793   Parameter    | Type      | Description
794   -------------|-----------|--------------
795   next\_check  | timestamp | **Optional.** The next check will be run at this time. If omitted, the current time is used.
796   force\_check | boolean   | **Optional.** Defaults to `false`. If enabled, the checks are executed regardless of time period restrictions and checks being disabled per object or on a global basis.
797
798 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
799
800 The example reschedules all services with the name "ping6" to immediately perform a check
801 (`next_check` default), ignoring any time periods or whether active checks are
802 allowed for the service (`force_check=true`).
803
804     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \
805     -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "force_check": true }' | python -m json.tool
806
807     {
808         "results": [
809             {
810                 "code": 200.0,
811                 "status": "Successfully rescheduled check for object 'localhost!ping6'."
812             }
813         ]
814     }
815
816
817 ### <a id="icinga2-api-actions-send-custom-notification"></a> send-custom-notification
818
819 Send a custom notification for hosts and services. This notification
820 type can be forced being sent to all users.
821
822 Send a `POST` request to the URL endpoint `/v1/actions/send-custom-notification`.
823
824   Parameter | Type    | Description
825   ----------|---------|--------------
826   author    | string  | **Required.** Name of the author, may be empty.
827   comment   | string  | **Required.** Comment text, may be empty.
828   force     | boolean | **Optional.** Default: false. If true, the notification is sent regardless of downtimes or whether notifications are enabled or not.
829
830 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
831
832 Example for a custom host notification announcing a global maintenance to
833 host owners:
834
835     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/send-custom-notification' \
836     -d '{ "type": "Host", "author": "icingaadmin", "comment": "System is going down for maintenance", "force": true }' | python -m json.tool
837
838     {
839         "results": [
840             {
841                 "code": 200.0,
842                 "status": "Successfully sent custom notification for object 'host0'."
843             },
844             {
845                 "code": 200.0,
846                 "status": "Successfully sent custom notification for object 'host1'."
847             }
848     }
849
850 ### <a id="icinga2-api-actions-delay-notification"></a> delay-notification
851
852 Delay notifications for a host or a service.
853 Note that this will only have an effect if the service stays in the same problem
854 state that it is currently in. If the service changes to another state, a new
855 notification may go out before the time you specify in the `timestamp` argument.
856
857 Send a `POST` request to the URL endpoint `/v1/actions/delay-notification`.
858
859   Parameter | Type      | Description
860   ----------|-----------|--------------
861   timestamp | timestamp | **Required.** Delay notifications until this timestamp.
862
863 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
864
865 Example:
866
867     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/delay-notification' \
868     -d '{ "type": "Service", "timestamp": 1446389894 }' | python -m json.tool
869
870     {
871         "results": [
872             {
873                 "code": 200.0,
874                 "status": "Successfully delayed notifications for object 'host0!service0'."
875             },
876             {
877                 "code": 200.0,
878                 "status": "Successfully delayed notifications for object 'host1!service1'."
879             }
880     }
881
882 ### <a id="icinga2-api-actions-acknowledge-problem"></a> acknowledge-problem
883
884 Allows you to acknowledge the current problem for hosts or services. By
885 acknowledging the current problem, future notifications (for the same state if `sticky` is set to `false`)
886 are disabled.
887
888 Send a `POST` request to the URL endpoint `/v1/actions/acknowledge-problem`.
889
890   Parameter | Type      | Description
891   ----------|-----------|--------------
892   author    | string    | **Required.** Name of the author, may be empty.
893   comment   | string    | **Required.** Comment text, may be empty.
894   expiry    | timestamp | **Optional.** If set, the acknowledgement will vanish after this timestamp.
895   sticky    | boolean   | **Optional.** If `true`, the default, the acknowledgement will remain until the service or host fully recovers.
896   notify    | boolean   | **Optional.** If `true`, a notification will be sent out to contacts to indicate this problem has been acknowledged. The default is false.
897
898 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
899
900 The following example acknowledges all services which are in a hard critical state and sends out
901 a notification for them:
902
903     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/acknowledge-problem?type=Service&filter=service.state==2&service.state_type=1' \
904     -d '{ "author": "icingaadmin", "comment": "Global outage. Working on it.", "notify": true }' | python -m json.tool
905
906     {
907         "results": [
908             {
909                 "code": 200.0,
910                 "status": "Successfully acknowledged problem for object 'example2.localdomain!ping4'."
911             },
912             {
913                 "code": 200.0,
914                 "status": "Successfully acknowledged problem for object 'example.localdomain!ping4'."
915             }
916     }
917
918
919 ### <a id="icinga2-api-actions-remove-acknowledgement"></a> remove-acknowledgement
920
921 Removes the acknowledgements for services or hosts. Once the acknowledgement has
922 been removed notifications will be sent out again.
923
924 Send a `POST` request to the URL endpoint `/v1/actions/remove-acknowledgement`.
925
926 A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
927
928 The example removes all service acknowledgements:
929
930     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-acknowledgement?type=Service' | python -m json.tool
931
932     {
933         "results": [
934             {
935                 "code": 200.0,
936                 "status": "Successfully removed acknowledgement for object 'host0!service0'."
937             },
938             {
939                 "code": 200.0,
940                 "status": "Successfully removed acknowledgement for object 'example2.localdomain!aws-health'."
941             }
942     }
943
944 ### <a id="icinga2-api-actions-add-comment"></a> add-comment
945
946 Adds a `comment` from an `author` to services or hosts.
947
948 Send a `POST` request to the URL endpoint `/v1/actions/add-comment`.
949
950   Parameter | Type   | Description
951   ----------|--------|--------------
952   author    | string | **Required.** Name of the author, may be empty.
953   comment   | string | **Required.** Comment text, may be empty.
954
955 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
956
957 The following example adds a comment for all `ping4` services:
958
959     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/add-comment?type=Service&filter=service.name==%22ping4%22' -d '{ "author": "icingaadmin", "comment": "Troubleticket #123456789 opened." }' | python -m json.tool
960     {
961         "results": [
962             {
963                 "code": 200.0,
964                 "legacy_id": 26.0,
965                 "name": "example.localdomain!ping4!example.localdomain-1446824161-0",
966                 "status": "Successfully added comment 'example.localdomain!ping4!example.localdomain-1446824161-0' for object 'example.localdomain!ping4'."
967             },
968             {
969                 "code": 200.0,
970                 "legacy_id": 27.0,
971                 "name": "example2.localdomain!ping4!example.localdomain-1446824161-1",
972                 "status": "Successfully added comment 'example2.localdomain!ping4!example.localdomain-1446824161-1' for object 'example2.localdomain!ping4'."
973             }
974         ]
975     }
976
977 ### <a id="icinga2-api-actions-remove-comment"></a> remove-comment
978
979 Remove the comment using its `name` attribute , returns `OK` if the
980 comment did not exist.
981 **Note**: This is **not** the legacy ID but the comment name returned by
982 Icinga 2 when [adding a comment](12-icinga2-api.md#icinga2-api-actions-add-comment).
983
984 Send a `POST` request to the URL endpoint `/v1/actions/remove-comment`.
985
986 A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host`, `Service` and `Comment`.
987
988 Example for a simple filter using the `comment` URL parameter:
989
990     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?comment=example2.localdomain!ping4!mbmif.local-1446986367-0' | python -m json.tool
991     {
992         "results": [
993             {
994                 "code": 200.0,
995                 "status": "Successfully removed comment 'example2.localdomain!ping4!mbmif.local-1446986367-0'."
996             }
997         ]
998     }
999
1000 Example for removing all service comments using a service name filter for `ping4`:
1001
1002     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?filter=service.name==%22ping4%22&type=Service' | python -m json.tool
1003     {
1004         "results": [
1005             {
1006                 "code": 200.0,
1007                 "status": "Successfully removed all comments for object 'example2.localdomain!ping4'."
1008             },
1009             {
1010                 "code": 200.0,
1011                 "status": "Successfully removed all comments for object 'example.localdomain!ping4'."
1012             }
1013         ]
1014     }
1015
1016
1017 ### <a id="icinga2-api-actions-schedule-downtime"></a> schedule-downtime
1018
1019 Schedule a downtime for hosts and services.
1020
1021 Send a `POST` request to the URL endpoint `/v1/actions/schedule-downtime`.
1022
1023   Parameter     | Type      | Description
1024   --------------|-----------|--------------
1025   author        | string    | **Required.** Name of the author.
1026   comment       | string    | **Required.** Comment text.
1027   start\_time   | timestamp | **Required.** Timestamp marking the beginning of the downtime.
1028   end\_time     | timestamp | **Required.** Timestamp marking the end of the downtime.
1029   duration      | integer   | **Required.** Duration of the downtime in seconds if `fixed` is set to false.
1030   fixed         | boolean   | **Optional.** Defaults to `true`. If true, the downtime is `fixed` otherwise `flexible`. See [downtimes](8-advanced-topics.md#downtimes) for more information.
1031   trigger\_name | string    | **Optional.** Sets the trigger for a triggered downtime. See [downtimes](8-advanced-topics.md#downtimes) for more information on triggered downtimes.
1032   child\_options | integer  | **Optional.** Schedule child downtimes. `0` does not do anything, `1` schedules child downtimes triggered by this downtime, `2` schedules non-triggered downtimes. Defaults to `0`.
1033
1034 In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host` and `Service`.
1035
1036 Example:
1037
1038     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime?type=Service&filter=service.name==%22ping4%22' -d '{ "start_time": 1446388806, "end_time": 1446389806, "duration": 1000, "author": "icingaadmin", "comment": "IPv4 network maintenance" }' | python -m json.tool
1039     {
1040         "results": [
1041             {
1042                 "code": 200.0,
1043                 "legacy_id": 2.0,
1044                 "name": "example2.localdomain!ping4!example.localdomain-1446822004-0",
1045                 "status": "Successfully scheduled downtime 'example2.localdomain!ping4!example.localdomain-1446822004-0' for object 'example2.localdomain!ping4'."
1046             },
1047             {
1048                 "code": 200.0,
1049                 "legacy_id": 3.0,
1050                 "name": "example.localdomain!ping4!example.localdomain-1446822004-1",
1051                 "status": "Successfully scheduled downtime 'example.localdomain!ping4!example.localdomain-1446822004-1' for object 'example.localdomain!ping4'."
1052             }
1053         ]
1054     }
1055
1056 ### <a id="icinga2-api-actions-remove-downtime"></a> remove-downtime
1057
1058 Remove the downtime using its `name` attribute , returns `OK` if the
1059 downtime did not exist.
1060 **Note**: This is **not** the legacy ID but the downtime name returned by
1061 Icinga 2 when [scheduling a downtime](12-icinga2-api.md#icinga2-api-actions-schedule-downtime).
1062
1063 Send a `POST` request to the URL endpoint `/v1/actions/remove-downtime`.
1064
1065 A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid types for this action are `Host`, `Service` and `Downtime`.
1066
1067 Example for a simple filter using the `downtime` URL parameter:
1068
1069     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?downtime=example.localdomain!ping4!mbmif.local-1446979168-6' | python -m json.tool
1070     {
1071         "results": [
1072             {
1073                 "code": 200.0,
1074                 "status": "Successfully removed downtime 'example.localdomain!ping4!mbmif.local-1446979168-6'."
1075             }
1076         ]
1077     }
1078
1079 Example for removing all host downtimes using a host name filter for `example.localdomain`:
1080
1081     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?filter=host.name==%22example.localdomain%22&type=Host' | python -m json.tool
1082     {
1083         "results": [
1084             {
1085                 "code": 200.0,
1086                 "status": "Successfully removed all downtimes for object 'example.localdomain'."
1087             }
1088         ]
1089     }
1090
1091 Example for removing a downtime from a host but not the services filtered by the author name. This example uses
1092 filter variables explained in the [advanced filters](12-icinga2-api.md#icinga2-api-advanced-filters) chapter.
1093
1094     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime' \
1095             -d $'{
1096       "type": "Downtime",
1097       "filter": "host.name == filterHost && !service && downtime.author == filterAuthor",
1098       "filter_vars": {
1099         "filterHost": "example.localdomain",
1100         "filterAuthor": "icingaadmin"
1101       }
1102     }' | python -m json.tool
1103
1104     {
1105         "results": [
1106             {
1107                 "code": 200.0,
1108                 "status": "Successfully removed downtime 'example.localdomain!mbmif.local-1463043129-3'."
1109             }
1110         ]
1111     }
1112
1113 ### <a id="icinga2-api-actions-shutdown-process"></a> shutdown-process
1114
1115 Shuts down Icinga2. May or may not return.
1116
1117 Send a `POST` request to the URL endpoint `/v1/actions/shutdown-process`.
1118
1119 This action does not support a target type or filter.
1120
1121 Example:
1122
1123     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/shutdown-process' | python -m json.tool
1124
1125     {
1126         "results": [
1127             {
1128                 "code": 200.0,
1129                 "status": "Shutting down Icinga 2."
1130             }
1131         ]
1132     }
1133
1134 ### <a id="icinga2-api-actions-restart-process"></a> restart-process
1135
1136 Restarts Icinga2. May or may not return.
1137
1138 Send a `POST` request to the URL endpoint `/v1/actions/restart-process`.
1139
1140 This action does not support a target type or filter.
1141
1142 Example:
1143
1144     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/restart-process' | python -m json.tool
1145
1146     {
1147         "results": [
1148             {
1149                 "code": 200.0,
1150                 "status": "Restarting Icinga 2."
1151             }
1152         ]
1153     }
1154
1155 ### <a id="icinga2-api-actions-generate-ticket"></a> generate-ticket
1156
1157 Generates a PKI ticket for [CSR auto-signing](6-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing).
1158 This can be used in combination with satellite/client setups requesting this ticket number.
1159
1160 Send a `POST` request to the URL endpoint `/v1/actions/generate-ticket`.
1161
1162   Parameter     | Type      | Description
1163   --------------|-----------|--------------
1164   cn            | string    | **Required.** The host's common name for which the ticket should be geenerated.
1165
1166 Example:
1167
1168     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/generate-ticket' \
1169     -d '{ "cn": "icinga2-client1.localdomain" }' | python -m json.tool
1170     {
1171         "results": [
1172             {
1173                 "code": 200.0,
1174                 "status": "Generated PKI ticket '4f75d2ecd253575fe9180938ebff7cbca262f96e' for common name 'icinga2-client1.localdomain'.",
1175                 "ticket": "4f75d2ecd253575fe9180938ebff7cbca262f96e"
1176             }
1177         ]
1178     }
1179
1180
1181 ## <a id="icinga2-api-event-streams"></a> Event Streams
1182
1183 You can subscribe to event streams by sending a `POST` request to the URL endpoint `/v1/events`.
1184 The following parameters need to be specified (either as URL parameters or in a JSON-encoded message body):
1185
1186   Parameter  | Type         | Description
1187   -----------|--------------|-------------
1188   types      | string array | **Required.** Event type(s). Multiple types as URL parameters are supported.
1189   queue      | string       | **Required.** Unique queue name. Multiple HTTP clients can use the same queue as long as they use the same event types and filter.
1190   filter     | string       | **Optional.** Filter for specific event attributes using [filter expressions](12-icinga2-api.md#icinga2-api-filters).
1191
1192 ### <a id="icinga2-api-event-streams-types"></a> Event Stream Types
1193
1194 The following event stream types are available:
1195
1196   Type                   | Description
1197   -----------------------|--------------
1198   CheckResult            | Check results for hosts and services.
1199   StateChange            | Host/service state changes.
1200   Notification           | Notification events including notified users for hosts and services.
1201   AcknowledgementSet     | Acknowledgement set on hosts and services.
1202   AcknowledgementCleared | Acknowledgement cleared on hosts and services.
1203   CommentAdded           | Comment added for hosts and services.
1204   CommentRemoved         | Comment removed for hosts and services.
1205   DowntimeAdded          | Downtime added for hosts and services.
1206   DowntimeRemoved        | Downtime removed for hosts and services.
1207   DowntimeStarted        | Downtime started for hosts and services.
1208   DowntimeTriggered      | Downtime triggered for hosts and services.
1209
1210 Note: Each type requires [API permissions](12-icinga2-api.md#icinga2-api-permissions)
1211 being set.
1212
1213 Example for all downtime events:
1214
1215     &types=DowntimeAdded&types=DowntimeRemoved&types=DowntimeTriggered
1216
1217
1218 ### <a id="icinga2-api-event-streams-filter"></a> Event Stream Filter
1219
1220 Event streams can be filtered by attributes using the prefix `event.`.
1221
1222 Example for the `CheckResult` type with the `exit_code` set to `2`:
1223
1224     &types=CheckResult&filter=event.check_result.exit_status==2
1225
1226 Example for the `CheckResult` type with the service [matching](18-library-reference.md#global-functions-match)
1227 the string pattern "random\*":
1228
1229     &types=CheckResult&filter=match%28%22random*%22,event.service%29
1230
1231
1232 ### <a id="icinga2-api-event-streams-response"></a> Event Stream Response
1233
1234 The event stream response is separated with new lines. The HTTP client
1235 must support long-polling and HTTP/1.1. HTTP/1.0 is not supported.
1236
1237 Example:
1238
1239     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/events?queue=michi&types=CheckResult&filter=event.check_result.exit_status==2'
1240
1241     {"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421319.7226390839,"type":"CheckResult"}
1242     {"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421324.7226390839,"type":"CheckResult"}
1243     {"check_result":{ ... },"host":"example.localdomain","service":"ping4","timestamp":1445421329.7226390839,"type":"CheckResult"}
1244
1245
1246 ## <a id="icinga2-api-status"></a> Status and Statistics
1247
1248 Send a `GET` request to the URL endpoint `/v1/status` to retrieve status information and statistics for Icinga 2.
1249
1250 Example:
1251
1252     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status' | python -m json.tool
1253     {
1254         "results": [
1255             {
1256                 "name": "ApiListener",
1257                 "perfdata": [ ... ],
1258                 "status": [ ... ]
1259             },
1260             ...
1261             {
1262                 "name": "IcingaAplication",
1263                 "perfdata": [ ... ],
1264                 "status": [ ... ]
1265             },
1266             ...
1267         ]
1268     }
1269
1270 You can limit the output by specifying a status type in the URL, e.g. `IcingaApplication`:
1271
1272     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status/IcingaApplication' | python -m json.tool
1273     {
1274         "results": [
1275             {
1276                 "perfdata": [],
1277                 "status": {
1278                     "icingaapplication": {
1279                         "app": {
1280                             "enable_event_handlers": true,
1281                             "enable_flapping": true,
1282                             "enable_host_checks": true,
1283                             "enable_notifications": true,
1284                             "enable_perfdata": true,
1285                             "enable_service_checks": true,
1286                             "node_name": "example.localdomain",
1287                             "pid": 59819.0,
1288                             "program_start": 1443019345.093372,
1289                             "version": "v2.3.0-573-g380a131"
1290                         }
1291                     }
1292                 }
1293             }
1294         ]
1295     }
1296
1297
1298 ## <a id="icinga2-api-config-management"></a> Configuration Management
1299
1300 The main idea behind configuration management is to allow external applications
1301 creating configuration packages and stages based on configuration files and
1302 directory trees. This replaces any additional SSH connection and whatnot to
1303 dump configuration files to Icinga 2 directly.
1304 In case you are pushing a new configuration stage to a package, Icinga 2 will
1305 validate the configuration asynchronously and populate a status log which
1306 can be fetched in a separated request.
1307
1308
1309 ### <a id="icinga2-api-config-management-create-package"></a> Creating a Config Package
1310
1311 Send a `POST` request to a new config package called `example-cmdb` in this example. This
1312 will create a new empty configuration package.
1313
1314     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \
1315     'https://localhost:5665/v1/config/packages/example-cmdb' | python -m json.tool
1316     {
1317         "results": [
1318             {
1319                 "code": 200.0,
1320                 "package": "example-cmdb",
1321                 "status": "Created package."
1322             }
1323         ]
1324     }
1325
1326 Package names starting with an underscore are reserved for internal packages and must not be used.
1327
1328 ### <a id="icinga2-api-config-management-create-config-stage"></a> Uploading configuration for a Config Package
1329
1330 Configuration files in packages are managed in stages.
1331 Stages provide a way to maintain multiple configuration versions for a package.
1332
1333 Send a `POST` request to the URL endpoint `/v1/config/stages` and add the name of an existing
1334 configuration package to the URL path (e.g. `example-cmdb`).
1335 The request body must contain the `files` attribute with the value being
1336 a dictionary of file targets and their content.
1337
1338 The file path requires one of these two directories inside its path:
1339
1340   Directory   | Description
1341   ------------|------------------------------------
1342   conf.d      | Local configuration directory.
1343   zones.d     | Configuration directory for cluster zones, each zone must be put into its own zone directory underneath. Supports the [cluster config sync](6-distributed-monitoring.md#distributed-monitoring-top-down-config-sync).
1344
1345 Example for a local configuration in the `conf.d` directory:
1346
1347     "files": { "conf.d/host1.conf": "object Host \"local-host\" { address = \"127.0.0.1\", check_command = \"hostalive\" }" }
1348
1349 Example for a host configuration inside the `satellite` zone in the `zones.d` directory:
1350
1351     "files": { "zones.d/satellite/host2.conf": "object Host \"satellite-host\" { address = \"192.168.1.100\", check_command = \"hostalive\" }" }
1352
1353
1354 The example below will create a new file called `test.conf` in the `conf.d`
1355 directory. Note: This example contains an error (`chec_command`). This is
1356 intentional.
1357
1358     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \
1359     -d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { chec_command = \"dummy\" }" } }' \
1360     'https://localhost:5665/v1/config/stages/example-cmdb' | python -m json.tool
1361     {
1362         "results": [
1363             {
1364                 "code": 200.0,
1365                 "package": "example-cmdb",
1366                 "stage": "example.localdomain-1441625839-0",
1367                 "status": "Created stage."
1368             }
1369         ]
1370     }
1371
1372 The Icinga 2 API returns the `package` name this stage was created for, and also
1373 generates a unique name for the `stage` attribute you'll need for later requests.
1374
1375 Icinga 2 automatically restarts the daemon in order to activate the new config stage.
1376 If the validation for the new config stage failed, the old stage and its configuration objects
1377 will remain active.
1378
1379 > **Note**
1380 >
1381 > Old stages are not purged automatically. You can [remove stages](12-icinga2-api.md#icinga2-api-config-management-delete-config-stage) that are no longer in use.
1382
1383 Icinga 2 will create the following files in the configuration package
1384 stage after configuration validation:
1385
1386   File        | Description
1387   ------------|--------------
1388   status      | Contains the [configuration validation](11-cli-commands.md#config-validation) exit code (everything else than 0 indicates an error).
1389   startup.log | Contains the [configuration validation](11-cli-commands.md#config-validation) output.
1390
1391 You can [fetch these files](12-icinga2-api.md#icinga2-api-config-management-fetch-config-package-stage-files)
1392 in order to verify that the new configuration was deployed successfully.
1393
1394
1395 ### <a id="icinga2-api-config-management-list-config-packages"></a> List Configuration Packages and their Stages
1396
1397 A list of packages and their stages can be retrieved by sending a `GET` request to the URL endpoint `/v1/config/packages`.
1398
1399 The following example contains one configuration package `example-cmdb`. The package does not currently
1400 have an active stage.
1401
1402     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/packages' | python -m json.tool
1403     {
1404         "results": [
1405             {
1406                 "active-stage": "",
1407                 "name": "example-cmdb",
1408                 "stages": [
1409                     "example.localdomain-1441625839-0"
1410                 ]
1411             }
1412         ]
1413     }
1414
1415
1416 ### <a id="icinga2-api-config-management-list-config-package-stage-files"></a> List Configuration Packages and their Stages
1417
1418 In order to retrieve a list of files for a stage you can send a `GET` request to
1419 the URL endpoint `/v1/config/stages`. You need to include
1420 the package name (`example-cmdb`) and stage name (`example.localdomain-1441625839-0`) in the URL:
1421
1422     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441625839-0' | python -m json.tool
1423     {
1424         "results": [
1425     ...
1426             {
1427                 "name": "startup.log",
1428                 "type": "file"
1429             },
1430             {
1431                 "name": "status",
1432                 "type": "file"
1433             },
1434             {
1435                 "name": "conf.d",
1436                 "type": "directory"
1437             },
1438             {
1439                 "name": "zones.d",
1440                 "type": "directory"
1441             },
1442             {
1443                 "name": "conf.d/test.conf",
1444                 "type": "file"
1445             }
1446         ]
1447     }
1448
1449 ### <a id="icinga2-api-config-management-fetch-config-package-stage-files"></a> Fetch Configuration Package Stage Files
1450
1451 Send a `GET` request to the URL endpoint `/v1/config/files` and add
1452 the package name, the stage name and the relative path to the file to the URL path.
1453
1454 > **Note**
1455 >
1456 > The returned files are plain-text instead of JSON-encoded.
1457
1458 The following example fetches the configuration file `conf.d/test.conf`:
1459
1460     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/files/example-cmdb/example.localdomain-1441625839-0/conf.d/test.conf'
1461
1462     object Host "cmdb-host" { chec_command = "dummy" }
1463
1464 You can fetch a [list of existing files](12-icinga2-api.md#icinga2-api-config-management-list-config-package-stage-files)
1465 in a configuration stage and then specifically request their content.
1466
1467 ### <a id="icinga2-api-config-management-config-package-stage-errors"></a> Configuration Package Stage Errors
1468
1469 Now that we don't have an active stage for `example-cmdb` yet seen [here](12-icinga2-api.md#icinga2-api-config-management-list-config-packages),
1470 there must have been an error.
1471
1472 In order to check for validation errors you can fetch the `startup.log` file
1473 by sending a `GET` request to the URL endpoint `/v1/config/files`. You must include
1474 the package name, stage name and the `startup.log` in the URL path.
1475
1476     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/files/example-cmdb/example.localdomain-1441133065-1/startup.log'
1477     ...
1478
1479     critical/config: Error: Attribute 'chec_command' does not exist.
1480     Location:
1481     /var/lib/icinga2/api/packages/example-cmdb/example.localdomain-1441133065-1/conf.d/test.conf(1): object Host "cmdb-host" { chec_command = "dummy" }
1482                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^
1483
1484     critical/config: 1 error
1485
1486 The output is similar to the manual [configuration validation](11-cli-commands.md#config-validation).
1487
1488 > **Note**
1489 >
1490 > The returned output is plain-text instead of JSON-encoded.
1491
1492
1493 ### <a id="icinga2-api-config-management-delete-config-stage"></a> Deleting Configuration Package Stage
1494
1495 You can send a `DELETE` request to the URL endpoint `/v1/config/stages`
1496 in order to purge a configuration stage. You must include the package and
1497 stage name inside the URL path.
1498
1499 The following example removes the failed configuration stage `example.localdomain-1441133065-1`
1500 in the `example-cmdb` configuration package:
1501
1502     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \
1503     'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441133065-1' | python -m json.tool
1504     {
1505         "results": [
1506             {
1507                 "code": 200.0,
1508                 "status": "Stage deleted."
1509             }
1510         ]
1511     }
1512
1513
1514 ### <a id="icinga2-api-config-management-delete-config-package"></a> Deleting Configuration Package
1515
1516 In order to completely purge a configuration package and its stages
1517 you can send a `DELETE` request to the URL endpoint `/v1/config/packages`
1518 with the package name in the URL path.
1519
1520 This example entirely deletes the configuration package `example-cmdb`:
1521
1522     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \
1523     'https://localhost:5665/v1/config/packages/example-cmdb' | python -m json.tool
1524     {
1525         "results": [
1526             {
1527                 "code": 200.0,
1528                 "package": "example-cmdb",
1529                 "status": "Deleted package."
1530             }
1531         ]
1532     }
1533
1534
1535 ## <a id="icinga2-api-types"></a> Types
1536
1537 You can retrieve the configuration object types by sending a `GET` request to URL
1538 endpoint `/v1/types`.
1539
1540 Each response entry in the results array contains the following attributes:
1541
1542   Attribute      | Type         | Description
1543   ---------------|--------------|---------------------
1544   name           | string       | The type name.
1545   plural_name    | string       | The plural type name.
1546   fields         | dictionary   | Available fields including details on e.g. the type and attribute accessibility.
1547   abstract       | boolean      | Whether objects can be instantiated for this type.
1548   base           | boolean      | The base type (e.g. `Service` inherits fields and prototype methods from `Checkable`).
1549   prototype_keys | string array | Available prototype methods.
1550
1551 In order to view a specific configuration object type specify its name inside the URL path:
1552
1553     $ curl -k -s -u root:icinga 'https://localhost:5665/v1/types/Object' | python -m json.tool
1554     {
1555         "results": [
1556             {
1557                 "abstract": false,
1558                 "fields": {
1559                     "type": {
1560                         "array_rank": 0.0,
1561                         "attributes": {
1562                             "config": false,
1563                             "navigation": false,
1564                             "no_user_modify": false,
1565                             "no_user_view": false,
1566                             "required": false,
1567                             "state": false
1568                         },
1569                         "id": 0.0,
1570                         "type": "String"
1571                     }
1572                 },
1573                 "name": "Object",
1574                 "plural_name": "Objects",
1575                 "prototype_keys": [
1576                     "clone",
1577                     "notify_attribute",
1578                     "to_string"
1579                 ]
1580             }
1581         ]
1582     }
1583
1584
1585 ## <a id="icinga2-api-console"></a> Console
1586
1587 You can inspect variables and execute other expressions by sending a `POST` request to the URL endpoint `/v1/console/execute-script`.
1588 In order to receive auto-completion suggestions, send a `POST` request to the URL endpoint `/v1/console/auto-complete-script`.
1589
1590 The following parameters need to be specified (either as URL parameters or in a JSON-encoded message body):
1591
1592   Parameter  | Type         | Description
1593   -----------|--------------|-------------
1594   session    | string       | **Optional.** The session ID. Ideally this should be a GUID or some other unique identifier.
1595   command    | string       | **Required.** Command expression for execution or auto-completion.
1596   sandboxed  | number       | **Optional.** Whether runtime changes are allowed or forbidden. Defaults to disabled.
1597
1598 The [API permission](12-icinga2-api.md#icinga2-api-permissions) `console` is required for executing
1599 expressions.
1600
1601 If you specify a session identifier, the same script context can be reused for multiple requests. This allows you to, for example, set a local variable in a request and use that local variable in another request. Sessions automatically expire after a set period of inactivity (currently 30 minutes).
1602
1603 Example for fetching the command line from the local host's last check result:
1604
1605     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/execute-script?command=get_host(NodeName).last_check_result.command&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756' | python -m json.tool
1606     {
1607         "results": [
1608             {
1609                 "code": 200.0,
1610                 "result": [
1611                     "/usr/local/sbin/check_ping",
1612                     "-H",
1613                     "127.0.0.1",
1614                     "-c",
1615                     "5000,100%",
1616                     "-w",
1617                     "3000,80%"
1618                 ],
1619                 "status": "Executed successfully."
1620             }
1621         ]
1622     }
1623
1624 Example for fetching auto-completion suggestions for the `Host.` type. This works in a
1625 similar fashion when pressing TAB inside the [console CLI command](11-cli-commands.md#cli-command-console):
1626
1627     $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/auto-complete-script?command=Host.&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756' | python -m json.tool
1628     {
1629         "results": [
1630             {
1631                 "code": 200.0,
1632                 "status": "Auto-completed successfully.",
1633                 "suggestions": [
1634                     "Host.type",
1635                     "Host.name",
1636                     "Host.prototype",
1637                     "Host.base",
1638                     "Host.register_attribute_handler",
1639                     "Host.clone",
1640                     "Host.notify_attribute",
1641                     "Host.to_string"
1642                 ]
1643             }
1644         ]
1645     }
1646
1647
1648 ## <a id="icinga2-api-clients"></a> API Clients
1649
1650 There are a couple of existing clients which can be used with the Icinga 2 API:
1651
1652 * [curl](http://curl.haxx.se) or any other HTTP client really
1653 * [Icinga 2 console (CLI command)](12-icinga2-api.md#icinga2-api-clients-cli-console)
1654 * [Icinga Studio](12-icinga2-api.md#icinga2-api-clients-icinga-studio)
1655 * [Icinga Web 2 Director](https://dev.icinga.org/projects/icingaweb2-modules)
1656
1657 Demo cases:
1658
1659 * [Dashing](https://github.com/Icinga/dashing-icinga2)
1660 * [API examples](https://github.com/Icinga/icinga2-api-examples)
1661
1662 Additional [programmatic examples](12-icinga2-api.md#icinga2-api-clients-programmatic-examples)
1663 will help you getting started using the Icinga 2 API in your environment.
1664
1665 ### <a id="icinga2-api-clients-icinga-studio"></a> Icinga Studio
1666
1667 Icinga Studio is a graphical application to query configuration objects provided by the API.
1668
1669 ![Icinga Studio Connection](images/icinga2-api/icinga2_api_icinga_studio_connect.png)
1670
1671 ![Icinga Studio Overview](images/icinga2-api/icinga2_api_icinga_studio_overview.png)
1672
1673 Please check the package repository of your distribution for available
1674 packages.
1675
1676 > **Note**
1677 > Icinga Studio does not currently support SSL certificate verification.
1678
1679 The Windows installer already includes Icinga Studio. On Debian and Ubuntu the package
1680 `icinga2-studio` can be used to install Icinga Studio.
1681
1682 ### <a id="icinga2-api-clients-cli-console"></a> Icinga 2 Console
1683
1684 By default the [console CLI command](11-cli-commands.md#cli-command-console) evaluates expressions in a local interpreter, i.e. independently from your Icinga 2 daemon. Using the `--connect` parameter you can use the Icinga 2  console to evaluate expressions via the API.
1685
1686 ### <a id="icinga2-api-clients-programmatic-examples"></a> API Clients Programmatic Examples
1687
1688 The programmatic examples use HTTP basic authentication and SSL certificate
1689 verification. The CA file is expected in `pki/icinga2-ca.crt`
1690 but you may adjust the examples for your likings.
1691
1692 The request method is `POST` using `X-HTTP-Method-Override: GET`
1693 which allows you to send a JSON request body. The examples request
1694 specific service attributes joined with host attributes. `attrs`
1695 and `joins` are therefore specified as array.
1696 The `filter` attribute [matches](18-library-reference.md#global-functions-match)
1697 on all services with `ping` in their name.
1698
1699 #### <a id="icinga2-api-clients-programmatic-examples-python"></a> Example API Client in Python
1700
1701 The following example uses **Python** and the `requests` and `json` module:
1702
1703     # pip install requests
1704     # pip install json
1705
1706     $ vim icinga2-api-example.py
1707
1708     #!/usr/bin/env python
1709     
1710     import requests, json
1711     
1712     # Replace 'localhost' with your FQDN and certificate CN
1713     # for SSL verification
1714     request_url = "https://localhost:5665/v1/objects/services"
1715     headers = {
1716             'Accept': 'application/json',
1717             'X-HTTP-Method-Override': 'GET'
1718             }
1719     data = {
1720             "attrs": [ "name", "state", "last_check_result" ],
1721             "joins": [ "host.name", "host.state", "host.last_check_result" ],
1722             "filter": "match(\"ping*\", service.name)",
1723     }
1724     
1725     r = requests.post(request_url,
1726             headers=headers,
1727             auth=('root', 'icinga'),
1728             data=json.dumps(data),
1729             verify="pki/icinga2-ca.crt")
1730     
1731     print "Request URL: " + str(r.url)
1732     print "Status code: " + str(r.status_code)
1733     
1734     if (r.status_code == 200):
1735             print "Result: " + json.dumps(r.json())
1736     else:
1737             print r.text
1738             r.raise_for_status()
1739
1740     $ python icinga2-api-example.py
1741
1742
1743 #### <a id="icinga2-api-clients-programmatic-examples-ruby"></a> Example API Client in Ruby
1744
1745 The following example uses **Ruby** and the `rest_client` gem:
1746
1747     # gem install rest_client
1748
1749     $ vim icinga2-api-example.rb
1750
1751     #!/usr/bin/ruby
1752     
1753     require 'rest_client'
1754     
1755     # Replace 'localhost' with your FQDN and certificate CN
1756     # for SSL verification
1757     request_url = "https://localhost:5665/v1/objects/services"
1758     headers = {
1759             "Accept" => "application/json",
1760             "X-HTTP-Method-Override" => "GET"
1761     }
1762     data = {
1763             "attrs" => [ "name", "state", "last_check_result" ],
1764             "joins" => [ "host.name", "host.state", "host.last_check_result" ],
1765             "filter" => "match(\"ping*\", service.name)",
1766     }
1767     
1768     r = RestClient::Resource.new(
1769             URI.encode(request_url),
1770             :headers => headers,
1771             :user => "root",
1772             :password => "icinga",
1773             :ssl_ca_file => "pki/icinga2-ca.crt")
1774     
1775     begin
1776             response = r.post(data.to_json)
1777     rescue => e
1778             response = e.response
1779     end
1780     
1781     puts "Status: " + response.code.to_s
1782     if response.code == 200
1783             puts "Result: " + (JSON.pretty_generate JSON.parse(response.body))
1784     else
1785             puts "Error: " + response
1786     end
1787
1788     $ ruby icinga2-api-example.rb
1789
1790 A more detailed example can be found in the [Dashing demo](https://github.com/Icinga/dashing-icinga2).
1791
1792 #### <a id="icinga2-api-clients-programmatic-examples-php"></a> Example API Client in PHP
1793
1794 The following example uses **PHP** and its `curl` library:
1795
1796     $ vim icinga2-api-example.php
1797
1798     #!/usr/bin/env php
1799     <?php
1800     # Replace 'localhost' with your FQDN and certificate CN
1801     # for SSL verification
1802     $request_url = "https://localhost:5665/v1/objects/services";
1803     $username = "root";
1804     $password = "icinga";
1805     $headers = array(
1806             'Accept: application/json',
1807             'X-HTTP-Method-Override: GET'
1808     );
1809     $data = array(
1810             attrs => array('name', 'state', 'last_check_result'),
1811             joins => array('host.name', 'host.state', 'host.last_check_result'),
1812             filter => 'match("ping*", service.name)',
1813     );
1814     
1815     $ch = curl_init();
1816     curl_setopt_array($ch, array(
1817             CURLOPT_URL => $request_url,
1818             CURLOPT_HTTPHEADER => $headers,
1819             CURLOPT_USERPWD => $username . ":" . $password,
1820             CURLOPT_RETURNTRANSFER => true,
1821             CURLOPT_CAINFO => "pki/icinga2-ca.crt",
1822             CURLOPT_POST => count($data),
1823             CURLOPT_POSTFIELDS => json_encode($data)
1824     ));
1825     
1826     $response = curl_exec($ch);
1827     if ($response === false) {
1828             print "Error: " . curl_error($ch) . "(" . $response . ")\n";
1829     }
1830     
1831     $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1832     curl_close($ch);
1833     print "Status: " . $code . "\n";
1834     
1835     if ($code == 200) {
1836             $response = json_decode($response, true);
1837             print_r($response);
1838     }
1839     ?>
1840
1841     $ php icinga2-api-example.php
1842
1843 #### <a id="icinga2-api-clients-programmatic-examples-perl"></a> Example API Client in Perl
1844
1845 The following example uses **Perl** and the `Rest::Client` module:
1846
1847     # perl -MCPAN -e 'install REST::Client'
1848     # perl -MCPAN -e 'install JSON'
1849     # perl -MCPAN -e 'install MIME::Base64'
1850     # perl -MCPAN -e 'install Data::Dumper'
1851
1852     $ vim icinga2-api-example.pl
1853
1854     #!/usr/bin/env perl
1855     
1856     use strict;
1857     use warnings;
1858     use REST::Client;
1859     use MIME::Base64;
1860     use JSON;
1861     use Data::Dumper;
1862     
1863     # Replace 'localhost' with your FQDN and certificate CN
1864     # for SSL verification
1865     my $request_host = "https://localhost:5665";
1866     my $userpass = "root:icinga";
1867     
1868     my $client = REST::Client->new();
1869     $client->setHost($request_host);
1870     $client->setCa("pki/icinga2-ca.crt");
1871     $client->addHeader("Accept", "application/json");
1872     $client->addHeader("X-HTTP-Method-Override", "GET");
1873     $client->addHeader("Authorization", "Basic " . encode_base64($userpass));
1874     my %json_data = (
1875             attrs => ['name', 'state', 'last_check_result'],
1876             joins => ['host.name', 'host.state', 'host.last_check_result'],
1877             filter => 'match("ping*", service.name)',
1878     );
1879     my $data = encode_json(\%json_data);
1880     $client->POST("/v1/objects/services", $data);
1881     
1882     my $status = $client->responseCode();
1883     print "Status: " . $status . "\n";
1884     my $response = $client->responseContent();
1885     if ($status == 200) {
1886             print "Result: " . Dumper(decode_json($response)) . "\n";
1887     } else {
1888             print "Error: " . $response . "\n";
1889     }
1890
1891     $ perl icinga2-api-example.pl
1892