forked from cloudfoundry/docs-services
-
Notifications
You must be signed in to change notification settings - Fork 2
/
api-v1.html.md.erb
900 lines (823 loc) · 24.3 KB
/
api-v1.html.md.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
---
title: Writing a v1 Cloud Foundry Service
---
There are two versions of the Cloud Foundry Services API. This page documents
v1.
<strong>DEPRECATED:</strong> We recommend that all new service brokers be
written against the <a href="api.html">version 2 API</a>.
Writing a service involves writing a service broker that obeys the API contract
between the Cloud Controller v2 (CC) and a v1 service broker.
Service brokers were previously called Service Gateways (GW).
The protocol is entirely RESTful HTTP, with _bidirectional communication_.
In addition to authentication there are six basic operations that take place,
described in this document.
An oversimplified example of making a broker that supports the 3 most basic
operations can be found here: https://github.com/geapi/cf-service-example.
<%= image_tag("../images/v1services.png", :width =>"960", :height=>"720", :style => 'background-color:#fff') %>
## <a id='authentication'></a>Authentication ##
_The Cloud Controller authenticates to a broker using a shared secret_
The broker must reject all requests not including the shared secret with a 401
unauthorized response.
The token is registered into the Cloud Controller by an admin user, usually
using the cf CLI gem which adds commands like `cf create-service-auth-token`.
Or one can directly make calls to the Cloud Controller v2 RESTful API to
register a new shared secret (called auth token).
_A broker authenticates to the Cloud Controller using a UAA token_
Like all API endpoints in the Cloud Controller, the broker must first obtain and
then include a valid Oauth2 token from UAA.
This token must include the scope `cloud_controller.admin`, because only this
scope has permission to modify the services catalog.
## <a id="catalog"></a>Catalog Management</a> ##
With v2 of the Cloud Controller, a broker is responsible for maintaining its
catalog of offerings and plans by issuing various RESTful API calls to the Cloud
Controller.
Normally the lifecycle is as follows:
1. On startup, the broker communicates with UAA to get an access token with
sufficient permissions to access the Cloud Controller (currently admin access).
1. It then downloads the catalog of all available service offerings and plans
from the Cloud Controller.
1. It issues POST requests to create missing offerings and plans.
Offerings include a URL to access the broker responsible for future
provision/bind requests.
1. It issues PUT requests to update existing offerings and plans that are not in
sync.
1. It issues DELETE requests to remove offerings and plans it no longer wants to
advertise.
All catalog management APIs are in the CloudController.
A service is identified by the combination of `[label, provider, version]`,
which must be unique.
A plan is identified by `[service_guid, name]`, which must also be unique.
We introduced the `unique_id` field in order to enable service brokers to change
service labels, providers, and versions, and to change plan names.
If a service broker sets a `unique_id` for its service in Cloud Controller, then
the broker can use the `unique_id` to identify the service, even after it has
changed the service name, etc.
The same is true for plans.
To generate a `unique_id`, try this [Online GUID
Generator](http://www.guidgenerator.com/ "Online GUID Generator").
### <a id='catalog-create-new'></a>Creating a new service in the catalog ###
`POST /v2/services`
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>label*</td>
<td>string</td>
<td>The type of service offered, like "mongodb".
This must match the name of the service used for the service-auth-token</td>
</tr>
<tr>
<td>provider*</td>
<td>string</td>
<td>The provider of the service, such as "core" or "mongolab"</td>
</tr>
<tr>
<td>url*</td>
<td>string</td>
<td>The callback URL of the broker</td>
</tr>
<tr>
<td>description*</td>
<td>string</td>
<td>Description to be displayed in CF frontends</td>
</tr>
<tr>
<td>version*</td>
<td>string</td>
<td>The version string of the service provided to be displayed to users, 5.5
for mysql "5.5".
Multiple of the same services can exist with different versions.</td>
</tr>
<tr>
<td>info_url</td>
<td>string</td>
<td>(Currently unused) A URL that users can visit to determine more
information about a service offering</td>
</tr>
<tr>
<td>acls</td>
<td>string</td>
<td>(Currently unused)</td>
</tr>
<tr>
<td>timeout</td>
<td>integer</td>
<td>(Currently unused) How long the Cloud Controller should wait for a broker
to finish an operation before giving up.</td>
</tr>
<tr>
<td>active</td>
<td>bool</td>
<td>Used as a hint to CF front-ends that a service is not active and can no
longer be provisioned (not enforced by the Cloud Controller)</td>
</tr>
<tr>
<td>extra</td>
<td>string</td>
<td>JSON-encoded-string of extra data to be used by frontend clients. For more information see <a href="catalog-metadata.html">Catalog Metadata</a>.</td>
</tr>
<tr>
<td>unique_id</td>
<td>string</td>
<td>A new identifier that must be globally unique.
This ID will be passed to the service broker as part of provision, bind,
etc. requests.
This "primary key" is easier to work with than the combination of
<code>[label, provider, version]</code> which also forms a "primary
key".</td>
</tr>
<tr>
<td>bindable</td>
<td>bool</td>
<td>If false, cloud controller will return an error to frontend clients when a
user requests to bind an app to an instance of the service.</td>
</tr>
<tr>
<td>tags</td>
<td>array of objects</td>
<td>Used by buildpacks and application libraries to parse credentials from the
VCAP_SERVICES environment variable.
Could also be used by frontend clients to filter marketplace services.</td>
</tr>
<tr>
<td>documentation_url</td>
<td>string</td>
<td>(Currently unused) Used by frontend clients to display a URL to
documentation for the service.</td>
</tr>
<tr>
<td>service_plans</td>
<td>array of objects</td>
<td>A list of service plan objects to created along as part of this service; see <a href="#catalog-create-plan">Creating a new plan in the catalog</a>.</td>
</tr>
</tbody>
</table>
<table border="1" class="nice">
<thead>
<tr>
<th>Response field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>metadata</td>
<td>object</td>
<td>Contains guid and the Cloud Controller URL for manipulating the newly
created resource</td>
</tr>
<tr>
<td>entity</td>
<td>object</td>
<td>Contains all the same fields as above</td>
</tr>
</tbody>
</table>
<table border="1" class="nice">
<thead>
<tr>
<th>Response code</th>
<th>Response meaning</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>201</td>
<td>Created</td>
<td>
Service successfully created, example response:
<pre><code>
{
"metadata" = > {
"guid" = > "9201fc22-ee74-42c8-9dcd-4425be183074",
"url" = > "/v2/services/9201fc22-ee74-42c8-9dcd-4425be183074",
"created_at" = > "2013-07-01 14:54:06 +0000",
"updated_at" = > nil
}, "entity" = > {
"label" = > "push-gateway-1.0",
"provider" = > "aws",
"url" = > "http://where.your.gateway.lives.org",
"description" = > "Your Gateway",
"version" = > "1.0",
"info_url" = > nil,
"active" = > false,
"unique_id" = > "pg-1.0",
"extra" = > nil,
"service_plans_url" = >
"/v2/services/9201fc22-ee74-42c8-9dcd-4425be183074/service_plans"
}
}
</pre></code>
</td>
</tr>
<tr>
<td>400</td>
<td>Bad request</td>
<td>one of: already defined, bad request, invalid params, missing field (error
message in the Cloud Controller log will have details as to why)</td>
</tr>
<tr>
<td>401/403</td>
<td>Unauthenticated/Forbidden</td>
<td>Invalid or missing UAA oauth2 token in request</td>
</tr>
<tr>
<td>500</td>
<td>Server error</td>
<td>Something in the Cloud Controller went wrong, check log</td>
</tr>
</tbody>
</table>
### <a id='catalog-update-service'></a>Updating a service in the catalog ###
`PUT /v2/services`
<table border="1" class="nice">
<thead>
<tr>
<th>Optional request query parameter</th>
<th>Possible values</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>collection-method</td>
<td>add<br/>replace</td>
<td>Merge any supplied plans with existing plans<br/>Replace existing plans
with supplied plans </td>
</tr>
</tbody>
</table>
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>label*<br/>provider*</br>version*</td>
<td>string</td>
<td>If `unique_id` is not provided, used to find the existing service to be
updated</td>
</tr>
<tr>
<td colspan="3"><em>Everything else same as create endpoint, except
`unique_id` cannot be included</em></td>
</tr>
</tbody>
</table>
### <a id='catalog-list-services'></a>Listing the services catalog ###
`GET /v2/services`
<table border="1" class="nice">
<thead>
<tr>
<th>Optional request query parameter</th>
<th>Possible values</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>limit</td>
<td>integer</td>
<td></td>
</tr>
<tr>
<td>offset</td>
<td>integer</td>
<td></td>
</tr>
<tr>
<td>urls-only</td>
<td>1</td>
<td>If 1 only return a list of URLs for each service</td>
</tr>
<tr>
<td>inline-relation-depth</td>
<td>0-3</td>
<td>Set to 1 to get plans as well<br/>Set to 2 to get plans &
instances<br/>Set to 3 to get plans & instances & bindings</td>
</tr>
<tr>
<td>q</td>
<td>string</td>
<td>Query to filter the returned service offerings, like `active:1`</td>
</tr>
</tbody>
</table>
<table border="1" class="nice">
<thead>
<tr>
<th>Response field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>metadata</td>
<td>object</td>
<td>Contains guid and the Cloud Controller URL for each service resource</td>
</tr>
<tr>
<td>entity</td>
<td>object</td>
<td>
<em>Contains all the same fields as create</em><br/>
Also contains "service_plans_url", a Cloud Controller URL to download the
list of plans.
May also contain a full list of plans, depending on query params
</td>
</tr>
</tbody>
</table>
### <a id='catalog-remove-service'></a>Removing a service from the catalog ###
`DELETE /v2/services/:guid`
No body or query parameters.
This request is expected to fail if there are plans, instances, or bindings
attached to this service, as they must be deleted first.
### <a id='catalog-create-plan'></a>Creating a new plan in the catalog ###
`POST /v2/service_plans`
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>name*</td>
<td>string</td>
<td>The name of the plan, unique when scoped by service GUID</td>
</tr>
<tr>
<td>free*</td>
<td>bool</td>
<td>Displayed by frontends, used by quota_definitions to determine whether an
org can provision a service</td>
</tr>
<tr>
<td>description*</td>
<td>string</td>
<td>Description to be displayed in CF frontends</td>
</tr>
<tr>
<td>extra</td>
<td>string</td>
<td>JSON-encoded-string of extra data to be used by frontend clients. For more information see <a href="catalog-metadata.html">Catalog Metadata</a>.</td>
</tr>
<tr>
<td>unique_id</td>
<td>string</td>
<td>A new identifier that must be unique.
This ID will be passed as part of provision, bind, etc. requests.
This "primary key" is easier to work with than the combination of [label,
provider, version] which also forms a "primary key".</td>
</tr>
<tr>
<td>public</td>
<td>bool</td>
<td>Whether a plan should be automatically visible for all users.
When false, the rules behind service_plan_visibilities are used to decide
visibility.</td>
</tr>
<tr>
<td>service_guid*</td>
<td>string</td>
<td>GUID of the parent service for this plan</td>
</tr>
</tbody>
</table>
<table border="1" class="nice">
<thead>
<tr>
<th>Response field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>metadata</td>
<td>object</td>
<td>Contains guid and the Cloud Controller URL for manipulating the newly
created resource</td>
</tr>
<tr>
<td>entity</td>
<td>object</td>
<td>
<em>Contains all the same fields as create</em>
</td>
</tr>
</tbody>
</table>
### <a id='catalog-list-plans'></a>Listing the plans ###
`GET /v2/service_plans`
<table border="1" class="nice">
<thead>
<tr>
<th>Optional request query parameter</th>
<th>Possible values</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>limit</td>
<td>integer</td>
<td></td>
</tr>
<tr>
<td>offset</td>
<td>integer</td>
<td></td>
</tr>
<tr>
<td>urls-only</td>
<td>1</td>
<td>If 1 only return a list of URLs for each plan</td>
</tr>
<tr>
<td>inline-relation-depth</td>
<td>0-2</td>
<td>Set to 1 to get instances & spaces & service as well<br/>Set to 2 to get
service & instances & spaces & bindings
</tr>
<tr>
<td>q</td>
<td>string</td>
<td>Query to filter the returned service offerings, like `name:something`</td>
</tr>
</tbody>
</table>
<table border="1" class="nice">
<thead>
<tr>
<th>Response field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>metadata</td>
<td>object</td>
<td>Contains guid and the Cloud Controller URL for each plan resource</td>
</tr>
<tr>
<td>entity</td>
<td>object</td>
<td>
<em>Contains all the same fields as create</em><br/>
Also contains "service_instances_url", a Cloud Controller URL to download
the list of instances, and "service_url", a Cloud Controller URL to the parent
service
</td>
</tr>
</tbody>
</table>
### <a id='catalog-update-plan'></a>Updating a plan in the catalog ###
`PUT /v2/service_plans/:guid`
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>service_guid*<br/>name*
<td>string</td>
<td>If `unique_id` is not provided, used to find the existing plan to be
updated</td>
</tr>
<tr>
<td colspan="3"><em>Everything else same as create endpoint, except
`unique_id` cannot be provided</em></td>
</tr>
</tbody>
</table>
### <a id='catalog-remove-plan'></a>Removing a plan from the catalog ###
`DELETE /v2/service_plans/:guid`
* No body
* No query parameters.
This request is expected to fail if there instances or bindings attached to this
plan, as they must be deleted first.
## <a id="provision"></a>Provisioning ##
When developers provision a service (using `cf create-service`), they issue an
API request to the Cloud Controller including the offering, plan, and space.
The Cloud Controller uses its database to determine which broker is responsible
for this offering and issues an API request synchronously to the broker to
provision the resources.
This request includes less information than the user-initiated request, because
brokers are supposed to not care about some CF concepts like users, spaces, and
organizations.
The broker must then provision the resource, if possible, and respond with a
"gateway identifier" (GWID) that can be used to identify the resource for future
operations.
In CF terms, what is created after provisioning is a "service instance".
No application should have access to the service instance until it has been
bound by the user, so usually no service credentials exist at the time of
provisioning.
To provision, the Cloud Controller sends a provision request to the broker.
The full request URL is determined by concatenating the URL in the catalog + the
path below.
`POST :service_url/gateway/v1/configurations`
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>unique_id*</td>
<td>string</td>
<td>The unique_id of the desired <strong>service_plan</strong> to be
provisioned</td>
</tr>
<tr>
<td>name*</td>
<td>string</td>
<td>The user-provided name of the new instance</td>
</tr>
<tr>
<td>email</td>
<td>string</td>
<td>The email address of the provisioning user</br><em>do not use</em></td>
</tr>
<tr>
<td>provider</td>
<td>string</td>
<td>The provider of the service to provision, in case the broker is
responsible for multiple services</td>
</tr>
<tr>
<td>label</td>
<td>string</td>
<td>The label of the service to provision, in case the broker is responsible
for multiple services</td>
</tr>
<tr>
<td>plan</td>
<td>string</td>
<td>The name of the plan to be provisioned</td>
</tr>
<tr>
<td>version</td>
<td>string</td>
<td>The version of the service to provision, in case the broker is responsible
for multiple versions</td>
</tr>
<tr>
<td>organization_guid</td>
<td>string</td>
<td>The GUID of the organization under which the service will be provisioned
(try not to use this)</td>
</tr>
<tr>
<td>space_guid</td>
<td>string</td>
<td>The GUID of the space under which the service will be provisioned (try not
to use this)</td>
</tr>
<tr>
<td>plan_option</td>
<td>string</td>
<td>(Currently unused) User-provided options for the instance</td>
</tr>
</tbody>
</table>
Brokers should respond with `200 OK` and a JSON response body containing fields
from the table below.
The Cloud Controller will interpret any non-2xx response codes as a failure to
provision.
Asterisks denote required fields.
<table border="1" class="nice">
<thead>
<tr>
<th>Response field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>service_id*</td>
<td>string</td>
<td>A broker-generated identifier that represents the resource, and will be
passed to the broker for future bind/deprovision requests</td>
</tr>
<tr>
<td>configuration*</td>
<td>object</td>
<td>The configuration used to provision this service, usually a copy of the
request attributes</td>
</tr>
<tr>
<td>credentials*</td>
<td>object</td>
<td>Any credentials that were generated as a result of provisioning, that the
broker would like to be stored in the Cloud Controller.</td>
</tr>
<tr>
<td>dashboard_url</td>
<td>string</td>
<td>If applicable, the URL that an end-user can visit to monitor/manage the
provisioned instances</td>
</tr>
</tbody>
</table>
## <a id="bind"></a>Binding ##
Binding is a developer-initiated intention (using `cf bind-service`) to make a
service instance available to a specific application, and it usually has side
effects (such as creating new credentials for an application to access a
database).
Like provisioning, the developer makes an API call to the Cloud Controller
including the instance ID and app ID to be bound, and the Cloud Controller makes
an API call to the broker including just the service instance ID (brokers don’t
know about apps).
The broker must then create a binding, if possible, and respond with both a GWID
and credentials.
For services where there is only 1 set of credentials to a logical resource,
binding can simply return the same credentials to each application,
though it will be impossible to properly revoke access to an application during
unbind.
To bind, the Cloud Controller sends a bind request to the broker.
The full request URL is determined by concatenating the URL in the catalog + the
path below.
For legacy reasons, a binding is known as a "handle" on the broker side.
`POST /gateway/v1/configurations/:service_id/handles`
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>service_id*</td>
<td>string</td>
<td>The broker-generated identifier that identifies the instance to be
bound</td>
</tr>
<tr>
<td>label*</td>
<td>string</td>
<td>The string "#{service.label}-#{service.version}", such as "mysql-5.5"</td>
</tr>
<tr>
<td>email*</td>
<td>string</td>
<td>The email address of the provisioning user<br/>
<em>do not use, but it it required to make a valid message</em>
</td>
</tr>
<tr>
<td>app_id</td>
<td>string</td>
<td>The identifier of the application that will receive the binding
credentials.<br/>
<em>Included in the cloud controller in commit f577e8444 on 12/3/2013 (it will
be included in cf-release v15X)</em>
</td>
</tr>
<tr>
<td>binding_options*</td>
<td>object</td>
<td>(Currently unused) User-provided options for the binding</td>
</tr>
</tbody>
</table>
Brokers should respond with `200 OK` and a JSON response body containing fields
from the table below.
The Cloud Controller will interpret any non-2xx response codes as a failure to
bind.
Asterisks denote required fields.
<table border="1" class="nice">
<thead>
<tr>
<th>Response field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>service_id*</td>
<td>string</td>
<td>An identifier that’s generated by the broker and will be passed to the
broker for future unbind requests, it’s really a "handle_id" not a
service_id.</td>
</tr>
<tr>
<td>configuration*</td>
<td>object</td>
<td>The configuration used to provision this service, usually a copy of the
request attributes</td>
</tr>
<tr>
<td>credentials*</td>
<td>object</td>
<td>The credentials that were generated as part of this binding.
These credentials will be passed to the bound application as part of the
VCAP_SERVICES environment variable.</td>
</tr>
</tbody>
</table>
## <a id="unbind"></a>Unbinding ##
Simply the opposite of bind, unbind is the developer-initiated intention to
revoke a specific application’s access to a service instance.
The developer makes an API call to the Cloud Controller, which makes an API call
to the broker including the GWID of the binding that should be destroyed.
If possible, the bound credentials should be destroyed so that application can
no longer access the resource.
To delete a binding, the Cloud Controller sends an unbind request to the broker.
The full request URL is determined by concatenating the URL in the catalog + the
path below.
`DELETE /gateway/v1/configurations/:service_id/handles/:handle_id`
* Note: the `service_id` and `handle_id` exist in both the URL and BODY, see
table:
<table border="1" class="nice">
<thead>
<tr>
<th>Request field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>service_id*</td>
<td>string</td>
<td>The broker service_id that was returned from the
<strong>provision</strong> response</td>
</tr>
<tr>
<td>handle_id*</td>
<td>string</td>
<td>The broker service_id that was returned from the <strong>binding</strong>
response</td>
</tr>
<tr>
<td>binding_options</td>
<td>string</td>
<td>(Currently Unused)</td>
</tr>
</tbody>
</table>
Brokers should respond with `200 OK` and a body that is null or `{}`.
[vcap-services-base](https://github.com/cloudfoundry/vcap-services-base) returns
`{}`.
The Cloud Controller will interpret any non-2xx response codes as a failure and
will not delete the binding from its database.
The Cloud Controller ignores contents of JSON bodies.
## <a id="deprovision"></a>Deprovisioning ##
Simply the opposite of provision, deprovision is the developer-initiated
intention to remove a specific service instance.
The developer makes an API call to the Cloud Controller, which makes an API call
to the broker including the GWID of the instance that should be destroyed.
The resources consumed by the service instance should be released, and hopefully
made available to future requests.
To delete a service instance, the Cloud Controller sends a deprovision request
to the broker.
The full request URL is determined by concatenating the URL in the catalog + the
path below.
`DELETE /gateway/v1/configurations/:service_id`
* No body
* No query parameters
The only argument, `service_id`, is the broker service_id that was returned from
the provision response.
The Cloud Controller deprovision request contains no body.
Brokers should respond with `200 OK` and a body that is null or `{}`.
[vcap-services-base](https://github.com/cloudfoundry/vcap-services-base) returns
`{}`.
The Cloud Controller interprets any non-2xx response codes as a failure and will
not delete the instance from its database.
The Cloud Controller ignores contents of JSON bodies.
## <a id="orphans"></a>Orphan Detection and Cleanup ##
The Cloud Controller is the source of truth, and the broker and the Cloud
Controller can end up disagreeing about which services and binding exist.
In this case, the broker is responsible for removing the bindings and instances
that don’t exist anymore in the Cloud Controller.
There are the Cloud Controller endpoints for getting a list of bindings and
instances, and the broker should use these to find orphans and prune them.