]> granicus.if.org Git - icinga2/blob - doc/9-icinga2-api.md
Update docs
[icinga2] / doc / 9-icinga2-api.md
1 # <a id="icinga2-api"></a> Icinga 2 API
2
3 ## <a id="icinga2-api-introduction"></a> Introduction
4
5 The Icinga 2 API allows you to manage configuration objects
6 and resources in a simple, programmatic way using HTTP requests.
7
8 The endpoints are logically separated allowing you to easily
9 make calls to
10
11 * [retrieve information](9-icinga2-api.md#icinga2-api-objects) (status, config)
12 * run [actions](9-icinga2-api.md#icinga2-api-actions) (reschedule checks, etc.)
13 * [create/update/delete configuration objects](9-icinga2-api.md#icinga2-api-objects)
14 * [manage configuration packages](9-icinga2-api.md#icinga2-api-config-management)
15 * subscribe to [event streams](9-icinga2-api.md#icinga2-api-event-streams)
16
17 This chapter will start with a general overview followed by
18 detailed information about specific endpoints.
19
20 ### <a id="icinga2-api-requests"></a> Requests
21
22 Any tool capable of making HTTP requests can communicate with
23 the API, for example [curl](http://curl.haxx.se).
24
25 Requests are only allowed to use the HTTPS protocol so that
26 traffic remains encrypted.
27
28 By default the Icinga 2 API listens on port `5665` sharing this
29 port with the cluster communication protocol. This can be changed
30 by setting the `bind_port` attribute in the [ApiListener](6-object-types.md#objecttype-apilistener)
31 configuration object in the `/etc/icinga2/features-available/api.conf`
32 file.
33
34 Supported request methods:
35
36   Method        | Usage
37   --------------|------------------------------------------------------
38   GET           | Retrieve information about configuration objects. Any request using the GET method is read-only and does not affect any objects.
39   POST          | Update attributes of a specified configuration object.
40   PUT           | Create a new object. The PUT request must include all attributes required to create a new object.
41   DELETE        | Remove an object created by the API. The DELETE method is idempotent and does not require any check if the object actually exists.
42
43 ### <a id="icinga2-api-http-statuses"></a> HTTP Statuses
44
45 The API will return standard [HTTP statuses](https://www.ietf.org/rfc/rfc2616.txt)
46 including error codes.
47
48 When an error occurs, the response body will contain additional information
49 about the problem and its source.
50
51 A status in the range of 200 generally means that the request was succesful
52 and no error was encountered.
53
54 Return codes within the 400 range indicate that there was a problem with the
55 request. Either you did not authenticate correctly, you are missing the authorization
56 for your requested action, the requested object does not exist or the request
57 was malformed.
58
59 A status in the range of 500 generally means that there was a server-side problem
60 and Icinga 2 is unable to process your request currently.
61
62 Ask your Icinga 2 system administrator to check the `icinga2.log` file for further
63 troubleshooting.
64
65
66 ### <a id="icinga2-api-responses"></a> Responses
67
68 Succesful requests will send back a response body containing a `results`
69 list. Depending on the number of affected objects in your request, the
70 results may contain one or more entries.
71
72 The [output](9-icinga2-api.md#icinga2-api-output) will be sent back as JSON object:
73
74
75     {
76         "results": [
77             {
78                 "code": 200.0,
79                 "status": "Object was created."
80             }
81         ]
82     }
83
84
85 ### <a id="icinga2-api-authentication"></a> Authentication
86
87 There are two different ways for authenticating against the Icinga 2 API:
88
89 * username and password using HTTP basic auth
90 * X.509 certificate with client CN
91
92 In order to configure a new API user you'll need to add a new [ApiUser](6-object-types.md#objecttype-apiuser)
93 configuration object. In this example `root` will be the basic auth username
94 and the `password` attribute contains the basic auth password.
95
96     vim /etc/icinga2/conf.d/api-users.conf
97
98     object ApiUser "root" {
99       password = icinga"
100     }
101
102 Alternatively you can use X.509 client certificates by specifying the `client_cn`
103 the API should trust.
104
105     vim /etc/icinga2/conf.d/api-users.conf
106
107     object ApiUser "api-clientcn" {
108       password = "CertificateCommonName"
109     }
110
111 An `ApiUser` object can have both methods configured. Sensitive information
112 such as the password will not be exposed through the API itself.
113
114 New installations of Icinga 2 will automatically generate a new `ApiUser`
115 named `root` with a generated password in the `/etc/icinga2/conf.d/api-users.conf`
116 file.
117 You can manually invoke the cli command `icinga2 api setup` which will generate
118 a new local CA, self-signed certificate and a new API user configuration.
119
120 Once the API user is configured make sure to restart Icinga 2:
121
122     # service icinga2 restart
123
124 Now pass the basic auth information to curl and send a GET request to the API:
125
126     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1'
127
128 In case you will get an `Unauthorized` error message make sure to
129 check the API user credentials.
130
131 ### <a id="icinga2-api-permissions"></a> Permissions
132
133 **TODO** https://dev.icinga.org/issues/9088
134
135 ### <a id="icinga2-api-parameters"></a> Parameters
136
137 Depending on the request method there are two ways of
138 passing parameters to the request:
139
140 * JSON body (`POST`, `PUT`)
141 * Query string (`GET`, `DELETE`)
142
143 Reserved characters by the HTTP protocol must be passed url-encoded as query string, e.g. a
144 space becomes `%20`.
145
146 Example for query string:
147
148     /v1/hosts?filter=match(%22nbmif*%22,host.name)&attrs=host.name&attrs=host.state
149
150 Example for JSON body:
151
152     { "attrs": { "address": "8.8.4.4", "vars.os" : "Windows" } }
153
154 **TODO**
155
156 #### <a id="icinga2-api-filters"></a> Filters
157
158 Use the same syntax as for apply rule expressions
159 for filtering specific objects.
160
161 Example for all services in NOT-OK state:
162
163     https://icinga.org:5665/v1/services?filter=service.state!=0
164
165 Example for matching all hosts by name (**Note**: `"` are url-encoded as `%22`):
166
167     https://icinga.org:5665/v1/hosts?filter=match(%22nbmif*%22,host.name)
168
169 **TODO**
170
171
172
173 ### <a id="icinga2-api-output-format"></a>Output Format
174
175 The request and reponse body contain a JSON encoded string.
176
177 ### <a id="icinga2-api-version"></a>Version
178
179 Each url contains the version string as prefix (currently "/v1").
180
181 ### <a id="icinga2-api-url-overview"></a>Url Overview
182
183
184 The Icinga 2 API provides multiple url endpoints
185
186   Url Endpoints | Description
187   --------------|----------------------------------------------------
188   /v1/actions   | Endpoint for running specific [API actions](9-icinga2-api.md#icinga2-api-actions).
189   /v1/config    | Endpoint for [managing configuration modules](9-icinga2-api.md#icinga2-api-config-management).
190   /v1/events    | Endpoint for subscribing to [API events](9-icinga2-api.md#icinga2-api-actions).
191   /v1/status    | Endpoint for receiving icinga2 [status and statistics](9-icinga2-api.md#icinga2-api-status).
192   /v1/types     | Endpoint for listing Icinga 2 configuration object types and their attributes.
193
194 Additionally there are endpoints for each [config object type](6-object-types.md#object-types):
195
196 **TODO** Update
197
198   Url Endpoints         | Description
199   ------------------|----------------------------------------------------
200   /v1/hosts                     | Endpoint for retreiving and updating [Host](6-object-types.md#objecttype-host) objects.
201   /v1/services          | Endpoint for retreiving and updating [Service](6-object-types.md#objecttype-service) objects.
202   /v1/notifications     | Endpoint for retreiving and updating [Notification](6-object-types.md#objecttype-notification) objects.
203   /v1/dependencies      | Endpoint for retreiving and updating [Dependency](6-object-types.md#objecttype-dependency) objects.
204   /v1/users                     | Endpoint for retreiving and updating [User](6-object-types.md#objecttype-user) objects.
205   /v1/checkcommands     | Endpoint for retreiving and updating [CheckCommand](6-object-types.md#objecttype-checkcommand) objects.
206   /v1/eventcommands     | Endpoint for retreiving and updating [EventCommand](6-object-types.md#objecttype-eventcommand) objects.
207   /v1/notificationcommands | Endpoint for retreiving and updating [NotificationCommand](6-object-types.md#objecttype-notificationcommand) objects.
208   /v1/hostgroups        | Endpoint for retreiving and updating [HostGroup](6-object-types.md#objecttype-hostgroup) objects.
209   /v1/servicegroups     | Endpoint for retreiving and updating [ServiceGroup](6-object-types.md#objecttype-servicegroup) objects.
210   /v1/usergroups        | Endpoint for retreiving and updating [UserGroup](6-object-types.md#objecttype-usergroup) objects.
211   /v1/zones                     | Endpoint for retreiving and updating [Zone](6-object-types.md#objecttype-zone) objects.
212   /v1/endpoints         | Endpoint for retreiving and updating [Endpoint](6-object-types.md#objecttype-endpoint) objects.
213   /v1/timeperiods       | Endpoint for retreiving and updating [TimePeriod](6-object-types.md#objecttype-timeperiod) objects.
214
215
216
217 ## <a id="icinga2-api-actions"></a> Actions
218
219 There are several actions available for Icinga 2 provided by the `actions` url endpoint.
220
221 In case you have been using the [external commands](5-advanced-topics.md#external-commands)
222 in the past, the API actions provide a yet more powerful interface with
223 filters and even more functionality.
224
225 Actions require specific target types (e.g. `type=Host`) and a [filter](9-icinga2-api.md#)
226
227 **TODO**
228
229 Action name                            | Parameters                        | Target types             | Notes
230 ---------------------------------------|-----------------------------------|--------------------------|-----------------------
231 process-check-result                   | exit_status; plugin_output; check_source; performance_data[]; check_command[]; execution_end; execution_start; schedule_end; schedule_start | Service; Host | -
232 reschedule-check                       | {next_check}; {(force_check)} | Service; Host | -
233 acknowledge-problem                    | author; comment; {timestamp}; {(sticky)}; {(notify)} | Service; Host | -
234 remove-acknowledgement                 | - | Service; Host | -
235 add-comment                            | author; comment | Service; Host | -
236 remove-comment                         | - | Service;Host | -
237 remove-comment-by-id                   | comment_id | - | -
238 delay-notifications                    | timestamp | Service;Host | -
239 add-downtime                           | start_time; end_time; duration; author; comment; {trigger_id}; {(fixed)} | Service; Host; ServiceGroup; HostGroup | Downtime for all services on host x?
240 remove-downtime                        | - | Service; Host | -
241 remove-downtime-by-id                  | downtime_id | - | -
242 send-custom-notification               | options[]; author; comment | Service; Host | -
243
244 enable-passive-checks                  | - | Service; Host; ServiceGroup; HostGroup | "System" as target?
245 disable-passive-checks                 | - | Service; Host; ServiceGroup; HostGroup | diable all passive checks for services of hosts y in hostgroup x?
246 enable-active-checks                   | - | Host; HostGroup | -
247 disable-active-checks                  | - | Host; HostGroup | -
248 enable-notifications                   | - | Service; Host; ServiceGroup; HostGroup | Enable all notifications for services of host x?
249 disable-notifications                  | - | Service; Host; ServiceGroup; HostGroup | -
250 enable-flap-detection                  | - | Service; Host; ServiceGroup; HostGroup | -
251 disable-flap-detection                 | - | Service; Host; ServiceGroup; HostGroup | -
252 enable-event-handler                   | - | Service; Host | -
253 disable-event-handler                  | - | Service; Host | -
254
255 enable-global-notifications            | - | - | -
256 disable-global-notifications           | - | - | -
257 enable-global-flap-detection           | - | - | -
258 disable-global-flap-detection          | - | - | -
259 enable-global-event-handlers           | - | - | -
260 disable-global-event-handlers          | - | - | -
261 enable-global-performance-data         | - | - | -
262 disable-global-performance-data        | - | - | -
263 start-global-executing-svc-checks      | - | - | -
264 stop-global-executing-svc-checks       | - | - | -
265 start-global-executing-host-checks     | - | - | -
266 stop-global-executing-host-checks      | - | - | -
267 shutdown-process                       | - | - | -
268 restart-process                        | - | - | -
269
270
271 Examples:
272
273 Reschedule a service check for all services in NOT-OK state:
274
275     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/actions/reschedule-check?filter=service.state!=0&type=Service' -X POST | python -m json.tool
276     {
277         "results": [
278             {
279                 "code": 200.0,
280                 "status": "Successfully rescheduled check for icinga.org!http."
281             },
282             {
283                 "code": 200.0,
284                 "status": "Successfully rescheduled check for icinga.org!disk."
285             },
286             {
287                 "code": 200.0,
288                 "status": "Successfully rescheduled check for icinga.org!disk /."
289             }
290         ]
291     }
292
293
294
295
296 ## <a id="icinga2-api-event-streams"></a> Event Streams
297
298 **TODO** https://dev.icinga.org/issues/9078
299
300 ## <a id="icinga2-api-status"></a> Status and Statistics
301
302 Contains a list of sub url endpoints which provide the status and statistics
303 of available and enabled features. Any filters are ignored.
304
305 Example for the main url endpoint `/v1/status`:
306
307     $ curl -k -s -u root:icinga 'https://icinga.org:5665/v1/status' | python -m json.tool
308     {
309         "results": [
310             {
311                 "name": "ApiListener",
312                                 "perfdata": [ ... ],
313                                 "status": [ ... ]
314             },
315             ...
316             {
317                 "name": "IcingaAplication",
318                                 "perfdata": [ ... ],
319                                 "status": [ ... ]
320             },
321             ...
322         ]
323     }
324
325 `/v1/status` is always available as virtual status url endpoint.
326 It provides all feature status information into a collected overview.
327
328 Example for the icinga application url endpoint `/v1/status/IcingaApplication`:
329
330     $ curl -k -s -u root:icinga 'https://icinga.org:5665/v1/status/IcingaApplication' | python -m json.tool
331     {
332         "results": [
333             {
334                 "perfdata": [],
335                 "status": {
336                     "icingaapplication": {
337                         "app": {
338                             "enable_event_handlers": true,
339                             "enable_flapping": true,
340                             "enable_host_checks": true,
341                             "enable_notifications": true,
342                             "enable_perfdata": true,
343                             "enable_service_checks": true,
344                             "node_name": "icinga.org",
345                             "pid": 59819.0,
346                             "program_start": 1443019345.093372,
347                             "version": "v2.3.0-573-g380a131"
348                         }
349                     }
350                 }
351             }
352         ]
353     }
354
355
356 ## <a id="icinga2-api-objects"></a> API Objects
357
358 Provides functionality for all configuration object url endpoints listed
359 [here](9-icinga2-api.md#icinga2-api-url-overview).
360
361 ### <a id="icinga2-api-objects"></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 If you add a new cluster instance, or boot an instance beeing offline
368 for a while, Icinga 2 takes care of the initial object sync for all
369 objects created by the API.
370
371 More information about distributed monitoring, cluster and its
372 configuration can be found [here](13-distributed-monitoring-ha.md#distributed-monitoring-high-availability).
373
374 ### <a id="icinga2-api-hosts"></a> Hosts
375
376 All object attributes are prefixed with their respective object type.
377
378 Example:
379
380     host.address
381
382 Output listing and url parameters use the same syntax.
383
384 #### <a id="icinga2-api-hosts-list"></a> List All Hosts
385
386 Send a `GET` request to `/v1/hosts` to list all host objects and
387 their attributes.
388
389     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts'
390
391
392 #### <a id="icinga2-api-hosts-create"></a> Create New Host Object
393
394 New objects must be created by sending a PUT request. The following
395 parameters need to be passed inside the JSON body:
396
397   Parameters    | Description
398   --------------|------------------------------------
399   name          | **Optional.** If not specified inside the url, this is **required**.
400   templates     | **Optional.** Import existing configuration templates, e.g. `generic-host`.
401   attrs         | **Required.** Set specific [Host](6-object-types.md#objecttype-host) object attributes.
402
403
404 If attributes are of the Dictionary type, you can also use the indexer format:
405
406     "attrs": { "vars.os": "Linux" }
407
408 Example:
409
410     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts/google.com' \
411     -X PUT \
412     -d '{ "templates": [ "generic-host" ], "attrs": { "address": "8.8.8.8", "vars.os" : "Linux" } }' \
413     | python -m json.tool
414     {
415         "results": [
416             {
417                 "code": 200.0,
418                 "status": "Object was created."
419             }
420         ]
421     }
422
423 **Note**: Host objects require the `check_command` attribute. In the example above the `generic-host`
424 template already provides such.
425
426 If the configuration validation fails, the new object will not be created and the response body
427 contains a detailed error message. The following example omits the required `check_command` attribute.
428
429     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts/google.com' \
430     -X PUT \
431     -d '{ "attrs": { "address": "8.8.8.8", "vars.os" : "Linux" } }' \
432     | python -m json.tool
433     {
434         "results": [
435             {
436                 "code": 500.0,
437                 "errors": [
438                     "Error: Validation failed for object 'google.com' of type 'Host'; Attribute 'check_command': Attribute must not be empty."
439                 ],
440                 "status": "Object could not be created."
441             }
442         ]
443     }
444
445 #### <a id="icinga2-api-hosts-show"></a> Show Host
446
447 Send a `GET` request including the host name inside the url:
448
449     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts/google.com'
450
451 You can select specific attributes by adding them as url parameters using `?attrs=...`. Multiple
452 attributes must be added one by one, e.g. `?attrs=host.address&attrs=host.name`.
453
454     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts/google.com?attrs=host.name&attrs=host.address' | python -m json.tool
455     {
456         "results": [
457             {
458                 "attrs": {
459                     "host.address": "8.8.8.8",
460                     "host.name": "google.com"
461                 }
462             }
463         ]
464     }
465
466 #### <a id="icinga2-api-hosts-modify"></a> Modify Host
467
468 Existing objects must be modifed by sending a `POST` request. The following
469 parameters need to be passed inside the JSON body:
470
471   Parameters    | Description
472   --------------|------------------------------------
473   name          | **Optional.** If not specified inside the url, this is **required**.
474   templates     | **Optional.** Import existing configuration templates, e.g. `generic-host`.
475   attrs         | **Required.** Set specific [Host](6-object-types.md#objecttype-host) object attributes.
476
477
478 If attributes are of the Dictionary type, you can also use the indexer format:
479
480     "attrs": { "vars.os": "Linux" }
481
482
483 Example for existing object `google.com`:
484
485     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts/google.com' \
486     -X POST \
487     -d '{ "attrs": { "address": "8.8.4.4", "vars.os" : "Windows" } }' \
488     | python -m json.tool
489     {
490         "results": [
491             {
492                 "code": 200.0,
493                 "name": "google.com",
494                 "status": "Attributes updated.",
495                 "type": "Host"
496             }
497         ]
498     }
499
500 #### <a id="icinga2-api-hosts-delete"></a> Delete Host
501
502 You can delete objects created using the API by sending a `DELETE`
503 request. Specify the object name inside the url.
504
505   Parameters    | Description
506   --------------|------------------------------------
507   cascade       | **Optional.** Delete objects depending on the deleted objects (e.g. services on a host).
508
509 Example:
510
511     $ curl -u root:icinga -k -s 'https://icinga.org:5665/v1/hosts/google.com?cascade=1' -X DELETE | python -m json.tool
512     {
513         "results": [
514             {
515                 "code": 200.0,
516                 "name": "google.com",
517                 "status": "Object was deleted.",
518                 "type": "Host"
519             }
520         ]
521     }
522
523
524
525 **TODO** Add more config objects
526
527
528
529 ## <a id="icinga2-api-config-management"></a> Configuration Management
530
531 The main idea behind configuration management is to allow external applications
532 creating configuration packages and stages based on configuration files and
533 directory trees. This replaces any additional SSH connection and whatnot to
534 dump configuration files to Icinga 2 directly.
535 In case you’re pushing a new configuration stage to a package, Icinga 2 will
536 validate the configuration asynchronously and populate a status log which
537 can be fetched in a separated request.
538
539 ### <a id="icinga2-api-config-management-create-package"></a> Create Config Package
540
541 Send a `POST` request to a new config package called `puppet` in this example. This
542 will create a new empty configuration package.
543
544     $ curl -k -s -u root:icinga -X POST https://icinga.org:5665/v1/config/packages/puppet | python -m json.tool
545     {
546         "results": [
547             {
548                 "code": 200.0,
549                 "package": "puppet",
550                 "status": "Created package."
551             }
552         ]
553     }
554
555 ### <a id="icinga2-api-config-management-create-config-stage"></a> Create Configuration to Package Stage
556
557 Send a `POST` request to the url endpoint `/v1/config/stages` including an existing
558 configuration package, e.g. `puppet`.
559 The request body must contain the `files` attribute with the value being
560 a dictionary of file targets and their content.
561
562 The example below will create a new file called `test.conf` underneath the `conf.d`
563 directory populated by the sent configuration.
564 The Icinga 2 API returns the `package` name this stage was created for, and also
565 generates a unique name for the `package` attribute you'll need for later requests.
566
567 Note: This example contains an error (`chec_command`), do not blindly copy paste it.
568
569     $ curl -k -s -u root:icinga -X POST -d '{ "files": { "conf.d/test.conf": "object Host \"cfg-mgmt\" { chec_command = \"dummy\" }" } }' https://icinga.org:5665/v1/config/stages/puppet | python -m json.tool
570     {
571         "results": [
572             {
573                 "code": 200.0,
574                 "package": "puppet",
575                 "stage": "nbmif-1441625839-0",
576                 "status": "Created stage."
577             }
578         ]
579     }
580
581 If the configuration fails, the old active stage will remain active.
582 If everything is successful, the new config stage is activated and live.
583 Older stages will still be available in order to have some sort of revision
584 system in place.
585
586 Icinga 2 automatically creates the following files in the main configuration package
587 stage:
588
589   File          | Description
590   --------------|---------------------------
591   status        | Contains the [configuration validation](8-cli-commands.md#config-validation) exit code (everything else than 0 indicates an error).
592   startup.log   | Contains the [configuration validation](8-cli-commands.md#config-validation) output.
593
594 You can [fetch these files](9-icinga2-api.md#icinga2-api-config-management-fetch-config-package-stage-files) via API call
595 after creating a new stage.
596
597 ### <a id="icinga2-api-config-management-list-config-packages"></a> List Configuration Packages and their Stages
598
599 List all config packages, their active stage and other stages.
600 That way you may iterate of all of them programmatically for
601 older revisions and their requests.
602
603 The following example contains one configuration package `puppet`.
604 The latter already has a stage created, but it is not active.
605
606     $ curl -k -s -u root:icinga https://icinga.org:5665/v1/config/packages | python -m json.tool
607     {
608         "results": [
609             {
610                 "active-stage": "",
611                 "name": "puppet",
612                 "stages": [
613                     "nbmif-1441625839-0"
614                 ]
615             }
616         ]
617     }
618
619 ### <a id="icinga2-api-config-management-list-config-package-stage-files"></a> List Configuration Packages and their Stages
620
621 Sent a `GET` request to the url endpoint `/v1/config/stages` including the package
622 (`puppet`) and stage (`nbmif-1441625839-0`) name.
623
624     $ curl -k -s -u root:icinga https://icinga.org:5665/v1/config/stages/puppet/nbmif-1441625839-0 | python -m json.tool
625     {
626         "results": [
627     ...
628             {
629                 "name": "startup.log",
630                 "type": "file"
631             },
632             {
633                 "name": "status",
634                 "type": "file"
635             },
636             {
637                 "name": "conf.d",
638                 "type": "directory"
639             },
640             {
641                 "name": "zones.d",
642                 "type": "directory"
643             },
644             {
645                 "name": "conf.d/test.conf",
646                 "type": "file"
647             }
648         ]
649     }
650
651
652 ### <a id="icinga2-api-config-management-fetch-config-package-stage-files"></a> Fetch Configuration Package Stage Files
653
654 Send a `GET` request to the url endpoint `/v1/config/files` including
655 the package name, the stage name and the relative path to the file.
656 Note: You cannot use dots in paths.
657
658 You can fetch a [list of existing files](9-icinga2-api.md#icinga2-api-config-management-list-config-package-stage-files)
659 in a configuration stage and then specifically request their content.
660
661 The following example fetches the faulty configuration inside `conf.d/test.conf`
662 for further analysis.
663
664     $ curl -k -s -u root:icinga https://icinga.org:5665/v1/config/files/puppet/nbmif-1441625839-0/conf.d/test.conf
665     object Host "cfg-mgmt" { chec_command = "dummy" }
666
667 Note: The returned files are plain-text instead of JSON-encoded.
668
669 ### <a id="icinga2-api-config-management-config-package-stage-errors"></a> Configuration Package Stage Errors
670
671 Now that we don’t have an active stage for `puppet` yet seen [here](9-icinga2-api.md#icinga2-api-config-management-list-config-packages),
672 there must have been an error.
673
674 Fetch the `startup.log` file and check the config validation errors:
675
676     $ curl -k -s -u root:icinga https://icinga.org:5665/v1/config/files/puppet/imagine-1441133065-1/startup.log
677     ...
678     
679     critical/config: Error: Attribute 'chec_command' does not exist.
680     Location:
681     /var/lib/icinga2/api/packages/puppet/imagine-1441133065-1/conf.d/test.conf(1): object Host "cfg-mgmt" { chec_command = "dummy" }
682                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^
683     
684     critical/config: 1 error
685
686 The output is similar to the manual [configuration validation](8-cli-commands.md#config-validation).
687