└── README.md /README.md: -------------------------------------------------------------------------------- 1 | BitBalloon REST API 2 | =================== 3 | 4 | BitBalloon is a hosting service for the programmable web. It understands your documents and provides an API to deploy sites, manage form submissions, inject javascript snippets and do intelligent updates of HTML documents. This is a REST-style API that uses JSON for serialization and OAuth 2 for authentication. 5 | 6 | Making a request 7 | ---------------- 8 | 9 | All URLs start with `https://www.bitballoon.com/api/v1/`. **SSL only**. The path is prefixed with the API version. If we change the API in backward-incompatible ways, we'll bump the version marker and maintain stable support for the old URLs. 10 | 11 | To make a request for all the sites you have access to, you'd append the sites index path to the base url to form something like https://www.bitballoon.com/api/v1/sites. In curl, that looks like: 12 | 13 | ```shell 14 | curl -H 'User-Agent: MyApp (yourname@example.com)' https://www.bitballoon.com/api/v1/sites?access_token=oauth2_access_token 15 | ``` 16 | 17 | Authenticating 18 | -------------- 19 | 20 | BitBalloon uses OAuth2 for authentication. All requests must use HTTPS. You'll need an application client key and a client secret before you can access the BitBalloon API. You can register a new application at [https://www.bitballoon.com/applications](https://www.bitballoon.com/applications). 21 | 22 | If you're making a public integration with BitBalloon for others to enjoy, you must use OAuth 2. This allows users to authorize your application to use BitBalloon on their behalf without having to copy/paste API tokens or touch sensitive login info. 23 | 24 | The Oauth2 end user authorization endpoint is `https://www.bitballoon.com/oauth/authorize`. 25 | 26 | Endpoints 27 | --------- 28 | 29 | * `/sites` all sites 30 | * `/sites/{site_id}/forms` all forms for a site 31 | * `/sites/{site_id}/submissions` all submissions for a site 32 | * `/sites/{site_id}/files` all files for a site 33 | * `/sites/{site_id}/snippets` all snippets to be injected into the HTML of a site 34 | * `/sites/{site_id}/metadata` a metadata object for a site (can be used in combination with the snippets) 35 | * `/sites/{site_id}/deploys` all deploys for a site 36 | * `/forms` all forms 37 | * `/forms/{form_id}/submissions` all submissions from a specific form 38 | * `/submissions` all form submissions 39 | * `/users` all users you have access to 40 | * `/users/{user_id}/sites` all sites for a specific user 41 | * `/users/{user_id}/forms` all forms for a specific user 42 | * `/users/{user_id}/submissions` all form submissions for a specific user 43 | * `/dns_records` dns records - resellers only 44 | * `/dns_records/{record_id}/dns_zones` dns zones - resellers only 45 | * `/access_tokens` access tokens - resellers only 46 | 47 | A note on the `site_id`: this can either be the actual `id` of a site, but it is interchangeable with the full domain for a site (some-site.bitballoon.com or site.example.com). 48 | 49 | Rate Limiting 50 | ============= 51 | 52 | To protect BitBalloon from getting flooded by automated deploys or misbehaving applications, the BitBalloon API is rate limited. 53 | 54 | You can make up to 200 requests per minute. 55 | 56 | You can check the returned HTTP headers of any API request to see your current rate limit status: 57 | 58 | ``` 59 | X-RateLimit-Limit: 200 60 | X-RateLimit-Remaining: 56 61 | X-RateLimit-Reset: 1372700873 62 | ``` 63 | 64 | If you need higher limits, please contact us. 65 | 66 | Pagination 67 | ========== 68 | 69 | Requests that return multiple items will be paginated to 100 items by default. You can specify further pages with the ?page parameter. You can also set a custom page size up to 100 with the ?per_page parameter. 70 | 71 | Note that page numbering is 1-based and that ommiting the ?page parameter will return the first page. 72 | 73 | ### Link Header 74 | 75 | The pagination info is included in the `Link` header. 76 | 77 | ``` 78 | Link: ; rel="next", 79 | ; rel="last" 80 | ``` 81 | 82 | Linebreak is included for readability. 83 | 84 | The possible rel values are: 85 | 86 | * `next` 87 | Shows the URL of the immediate next page of results. 88 | * `last` 89 | Shows the URL of the last page of results. 90 | * `prev` 91 | Shows the URL of the immediate previous page of results. 92 | 93 | 94 | Sites 95 | ===== 96 | 97 | The `/sites` endpoint allows you to access the sites deployed on BitBalloon. 98 | 99 | Get Sites 100 | --------- 101 | 102 | * `GET /sites` will return all sites you have access to. 103 | 104 | ```json 105 | [ 106 | { 107 | "id":"3970e0fe-8564-4903-9a55-c5f8de49fb8b", 108 | "premium":false, 109 | "claimed":true, 110 | "name":"synergy", 111 | "custom_domain":"www.example.com", 112 | "url":"http://www.example.com", 113 | "admin_url":"https://www.bitballoon.com/sites/synergy", 114 | "screenshot_url":null, 115 | "created_at":"2013-09-17T05:13:08Z", 116 | "updated_at":"2013-09-17T05:13:19Z", 117 | "user_id":{"51f60d2d5803545326000005"}, 118 | } 119 | ] 120 | ``` 121 | 122 | Get Site 123 | -------- 124 | 125 | * `GET /sites/3970e0fe-8564-4903-9a55-c5f8de49fb8b` will return the site from its ID 126 | * `GET /sites/www.example.com` will return the site matching the domain `www.example.com` 127 | 128 | ```json 129 | { 130 | "id":"3970e0fe-8564-4903-9a55-c5f8de49fb8b", 131 | "premium":false, 132 | "claimed":true, 133 | "name":"synergy", 134 | "custom_domain":"www.example.com", 135 | "notification_email":"me@example.com", 136 | "url":"http://www.example.com", 137 | "admin_url":"https://www.bitballoon.com/sites/synergy", 138 | "screenshot_url":null, 139 | "created_at":"2013-09-17T05:13:08Z", 140 | "updated_at":"2013-09-17T05:13:19Z", 141 | "user_id":{"51f60d2d5803545326000005"}, 142 | } 143 | ``` 144 | 145 | Create Site 146 | ----------- 147 | 148 | Creating a site will initiate a new deploy. You can either create a new site with a list of files you intend to upload, or by posting a ZIP file. 149 | 150 | ### POST a ZIP file 151 | 152 | * `POST /sites` with `zip=zip-file`. You must use `Content-Type: multipart/form-data` to send the zip file in a property called `zip`. 153 | 154 | ```json 155 | { 156 | "id": "3970e0fe-8564-4903-9a55-c5f8de49fb8b", 157 | "subdomain": "some-autogenerated-subdomain", 158 | "url": "http://some-autogenerated-subdomain.bitballoon.com", 159 | "state": "processing", 160 | "required": [] 161 | } 162 | ``` 163 | 164 | This will return `201 Created` with the API URL for the new site in the `Location` header, along with a simplified JSON representation of the site. The site will be in the `processing` state and you can poll the URL in the `Location` header until the state has changed to either `ready` or `error`. 165 | 166 | Here's an example of creating a new site from a zip file called `landing.zip` via Curl (assuming you've gone through the process to get an oauth access_token) 167 | 168 | ```bash 169 | curl -F "zip=@landing.zip;type=application/zip" https://www.bitballoon.com/api/v1/sites?access_token={access_token} 170 | ``` 171 | 172 | ### POST a list of files 173 | 174 | * `POST /sites` with `{files: {"/index.html": "SHA1_OF_YOUR_INDEX_HTML"}}` will create a new site in the `uploading` state. You must use `Content-Type: application/json` 175 | 176 | The files object should contain all the files you wish to upload for this deploy, together with a SHA1 of the content of each file. 177 | 178 | ```json 179 | { 180 | "id": "3970e0fe-8564-4903-9a55-c5f8de49fb8b", 181 | "subdomain": "some-autogenerated-subdomain", 182 | "url": "http://some-autogenerated-subdomain.bitballoon.com", 183 | "state": "uploading", 184 | "required": ["SHA1_OF_YOUR_INDEX_HTML"] 185 | } 186 | ``` 187 | 188 | This will return `201 Created` with the API URL for the new site in the `Location` header, along with a simplified JSON representation of the site. The `required` property will give you a list of files you need to upload. BitBalloon will inspect the SHA1s you sent in the request. You'll only need to upload the files BitBalloon doesn't have on its servers. The `state` can be either `uploading` or `processing` depending on whether or not you need to upload any more files. 189 | 190 | To upload any required files, use the `PUT /sites/{site_id}/files/{path}` endpoint for each file. Once all the files are uploaded, the processing of the site will begin. 191 | 192 | Update Site 193 | ----------- 194 | 195 | * `PATCH /sites/{site_id}` will let you update some attributes on a site 196 | * `PUT /sites/{site_id}` will let you update some attributes on a site 197 | 198 | This lets you update the `name`, `custom_domain`, `password` and `notification_email` fields of a site. 199 | 200 | 201 | Destroy Site 202 | ------------ 203 | 204 | * `DELETE /sites/{site_id}` will permanently delete a site 205 | * `DELETE /sites/{site_domain}` will permanently delete a site 206 | 207 | This will return `200 OK`. 208 | 209 | 210 | Submissions 211 | =========== 212 | 213 | The `/submissions` endpoint gives access to the form submissions of your BitBalloon sites. You can scope submissions to a specific site (`/sites/{site_id}/submissions`) or to a specific form (`/forms/{form_id}/submissions`). 214 | 215 | Get Submissions 216 | --------------- 217 | 218 | * `GET /submissions` will return a list of form submissions 219 | 220 | ```json 221 | [ 222 | { 223 | "id":"5231110b5803540aeb000019", 224 | "number":13, 225 | "title":null, 226 | "email":"test@example.com", 227 | "name":"Mathias Biilmann", 228 | "first_name":"Mathias", 229 | "last_name":"Biilmann", 230 | "company":"BitBalloon", 231 | "summary":"Hello, World", 232 | "body":"Hello, World", 233 | "data": { 234 | "email":"test@example.com", 235 | "name": "Mathias Biilmann", 236 | "ip":"127.0.0.1" 237 | }, 238 | "created_at":"2013-09-12T00:55:39Z", 239 | "site_url":"http://synergy.bitballoon.com" 240 | } 241 | ] 242 | ``` 243 | 244 | Forms 245 | ===== 246 | 247 | The `/forms` endpoint allow you to access forms from your BitBalloon sites. You can scope forms to a specific site with `/sites/{site_id}/forms`. 248 | 249 | Get Forms 250 | --------- 251 | 252 | * `GET /forms` will return a list of forms 253 | 254 | ```json 255 | [ 256 | { 257 | "id":"ac0865cc46440b1e64666f520e8d88d670c8a2f6", 258 | "site_id":"0d3a9d2f-ef94-4380-93df-27ee400e2048", 259 | "name":"Landing Page", 260 | "paths":["/index"], 261 | "submission_count":3, 262 | "fields": [ 263 | {"name":"name","type":"text"}, 264 | {"name":"email","type":"email"}, 265 | {"name":"phone","type":"text"}, 266 | {"name":"company","type":"text"}, 267 | {"name":"website","type":"url"}, 268 | {"name":"number_of_employees","type":"select"} 269 | ], 270 | "created_at":"2013-09-18T20:26:19Z" 271 | } 272 | ] 273 | ``` 274 | 275 | Files 276 | ===== 277 | 278 | All files deployed by BitBalloon can be read, updated and deleted through the API. Where the public URL of a file will serve the processed version, the files accessed through the API are the original uploaded files. Any changes to a file will trigger a reprocessing of the site and a new deploy will be stored in the site history. This means all changes made through the API can always be rolled back by the user through the dashboard UI. 279 | 280 | Get Files 281 | --------- 282 | 283 | * `GET /sites/{site_id}/files` will return a list of all the files in the current deploy 284 | 285 | ```json 286 | [ 287 | {"id":"/index.html", 288 | "path":"/index.html", 289 | "sha":"20828dcdf2cd07e5980fe52759101591bf5014ab", 290 | "mime_type":"text/html", 291 | "size":27232 292 | } 293 | ] 294 | ``` 295 | 296 | Get File 297 | -------- 298 | 299 | * `GET /sites/{site_id}/files/{path-to-file}` returns the file 300 | 301 | ```json 302 | {"id":"/index.html", 303 | "path":"/index.html", 304 | "sha":"20828dcdf2cd07e5980fe52759101591bf5014ab", 305 | "mime_type":"text/html", 306 | "size":27232 307 | } 308 | ``` 309 | 310 | You can get the raw contents of the file by using the custom media type `application/vnd.bitballoon.v1.raw` as the Content-Type of your HTTP request. 311 | 312 | Put File 313 | -------- 314 | 315 | * `PUT /sites/{site_id}/files/{path-to-file}` will add or update a file, reprocess all assets and create a new deploy 316 | 317 | The request body will be used as the new content for this file. If the site is still in uploading mode (after creating a site with a list of files) and this is the last file 318 | 319 | Delete File 320 | ----------- 321 | 322 | * `DELETE /sites/{site_id}/files/{path-to-file}` will delete a file from the site. 323 | 324 | Note that this creates a new version of the site without the deleted file. The old version can still be rolled back and the file does not get deleted from BitBalloon's servers. 325 | 326 | Snippets 327 | ======== 328 | 329 | Snippets are code snippets that will be injected into every HTML page of the website, either right before the closing head tag or just before the closing body tag. Each snippet can specify code for all pages and code that just get injected into "Thank you" pages shown after a successful form submissions. 330 | 331 | Get Snippets 332 | ------------ 333 | 334 | * `GET /sites/{site_id}/snippets` get a list of snippets specific to this site (a reseller may set global snippets that won't be included in this list) 335 | 336 | ```json 337 | [ 338 | { 339 | "id":0, 340 | "title":"Test", 341 | "general":"\u003Cscript\u003Ealert(\"Hello\")\u003C/script\u003E", 342 | "general_position":"head", 343 | "goal":"", 344 | "goal_position":"footer" 345 | } 346 | ] 347 | ``` 348 | 349 | The `general` property is the code that will be injected right before either the head or body end tag. The `general_position` can be `head` or `footer` and determines whether to inject the code in the head element or before the closing body tag. 350 | 351 | The `goal` property is the code that will be injected into the "Thank you" page after a form submission. `goal_position` determines where to inject this code. 352 | 353 | Get Snippet 354 | ----------- 355 | 356 | * `GET /sites/{site_id}/snippets/{snippet_id}` get a specific snippet 357 | 358 | ```json 359 | { 360 | "id":0, 361 | "title":"Test", 362 | "general":"\u003Cscript\u003Ealert(\"Hello\")\u003C/script\u003E", 363 | "general_position":"head", 364 | "goal":"", 365 | "goal_position":"footer" 366 | } 367 | ``` 368 | 369 | Add Snippet 370 | -------------- 371 | 372 | * `POST /sites/{site_id}/snippets` add a new snippet to a site. 373 | 374 | Update Snippet 375 | -------------- 376 | 377 | * `PUT /sites/{site_id}/snippets/{snippet_id}` replace a snippet. 378 | 379 | Delete Snippet 380 | -------------- 381 | 382 | * `DELETE /sites/{site_id}/snippets/{snippet_id}` delete a snippet. 383 | 384 | Metadata 385 | ======== 386 | 387 | Each site has a metadata object. The properties of the metadata object can be used within the snippets for a site by sing the [Liquid](https://github.com/Shopify/liquid) template syntax. 388 | 389 | Get Metadata 390 | ------------ 391 | 392 | * `GET /sites/{site_id}/metadata` get the metadata for a site 393 | 394 | ```json 395 | { 396 | "my_meta_key": "my_meta_value" 397 | } 398 | ``` 399 | 400 | Update Metadata 401 | --------------- 402 | 403 | * `PUT /sites/{site_id}/metadata` replace the metdata object with a new metadata object 404 | 405 | Deploys 406 | ======= 407 | 408 | You can access all deploys for a specific site. 409 | 410 | Get Deploys 411 | ------------ 412 | 413 | * `GET /sites/{site_id}/deploys` a list of all deploys 414 | 415 | ```json 416 | [ 417 | { 418 | "id":"52465f435803544542000001", 419 | "premium":false, 420 | "claimed":true, 421 | "name":"synergy", 422 | "custom_domain":"www.example.com", 423 | "notification_email:"me@example.com", 424 | "url":"http://www.example.com", 425 | "deploy_url": "http://52465f435803544542000001.some-site.bitballoon.com", 426 | "admin_url":"https://www.bitballoon.com/sites/synergy", 427 | "screenshot_url":null, 428 | "created_at":"2013-09-17T05:13:08Z", 429 | "updated_at":"2013-09-17T05:13:19Z", 430 | "user_id":{"51f60d2d5803545326000005"}, 431 | "state": "old" 432 | } 433 | ] 434 | ``` 435 | 436 | Get Deploy 437 | ---------- 438 | 439 | * `GET /sites/{site_id}/deploys/{deploy_id}` a specific deploy 440 | 441 | ```json 442 | { 443 | "id":"52465f435803544542000001", 444 | "premium":false, 445 | "claimed":true, 446 | "name":"synergy", 447 | "custom_domain":"www.example.com", 448 | "notification_email:"me@example.com", 449 | "url":"http://www.example.com", 450 | "deploy_url": "http://52465f435803544542000001.some-site.bitballoon.com", 451 | "admin_url":"https://www.bitballoon.com/sites/synergy", 452 | "screenshot_url":null, 453 | "created_at":"2013-09-17T05:13:08Z", 454 | "updated_at":"2013-09-17T05:13:19Z", 455 | "user_id":{"51f60d2d5803545326000005"}, 456 | "state": "old" 457 | } 458 | ``` 459 | 460 | Restore Deploy 461 | -------------- 462 | 463 | * `POST /sites/{site_id}/deploys/{deploy_id}/restore` restore an old deploy and make it the live version of the site 464 | 465 | ```json 466 | { 467 | "id":"52465f435803544542000001", 468 | "premium":false, 469 | "claimed":true, 470 | "name":"synergy", 471 | "custom_domain":"www.example.com", 472 | "notification_email:"me@example.com", 473 | "url":"http://www.example.com", 474 | "deploy_url": "http://52465f435803544542000001.some-site.bitballoon.com", 475 | "admin_url":"https://www.bitballoon.com/sites/synergy", 476 | "screenshot_url":null, 477 | "created_at":"2013-09-17T05:13:08Z", 478 | "updated_at":"2013-09-17T05:13:19Z", 479 | "user_id":{"51f60d2d5803545326000005"}, 480 | "state": "current" 481 | } 482 | ``` 483 | 484 | Users 485 | ===== 486 | 487 | Mainly useful for reseller admins. Lets you access all users under your reseller account. 488 | 489 | Get Users 490 | --------- 491 | 492 | * `GET /users` get a list users you have access to 493 | 494 | ```json 495 | [ 496 | { 497 | "id": "52465eb05803543960000015", 498 | "email":"user@example.com", 499 | "affiliate_id":"", 500 | "site_count":1, 501 | "created_at":"2013-09-28T04:44:32Z", 502 | "last_login":"2013-09-28T04:44:33Z" 503 | } 504 | ] 505 | ``` 506 | 507 | Once you have a user id you can query sites, forms and submissions scoped to that user (ie. /users/{user_id}/sites). 508 | 509 | DNS Zones 510 | ========= 511 | 512 | **Resellers only**. Manage DNS Zones 513 | 514 | Get DNS Zones 515 | ------------- 516 | 517 | * `GET /dns_zones` get a list of DNS zones 518 | 519 | ```json 520 | [ 521 | { 522 | "id": "5286d0aa58035476d0000005", 523 | "name":"www.example.com", 524 | "user_id":"52841ed05803545ef0000001", 525 | "created_at":"2013-11-16T01:55:54Z", 526 | "updated_at":"2013-11-16T01:55:54Z" 527 | } 528 | ] 529 | ``` 530 | 531 | Create DNS Zone 532 | --------------- 533 | 534 | * `POST /dns_zones` create a new dns zone, arguments: `name` 535 | 536 | Returns 201 on successful creation 537 | 538 | Delete DNS Zone 539 | --------------- 540 | 541 | * `DELETE /dns_zones/{zone_id}` delete a dns zone 542 | 543 | Get records for a zone 544 | ---------------------- 545 | 546 | * `GET /dns_zones/{zone_id}/dns_records` get a list of dns records 547 | 548 | ```json 549 | [ 550 | { 551 | "id":"5286d29658035476d0000006", 552 | "hostname":"www", 553 | "type":"CNAME", 554 | "value":"bitballoon.com", 555 | "ttl":"500", 556 | "domain_id":"5286d0aa58035476d0000005" 557 | } 558 | ] 559 | ``` 560 | 561 | Create a DNS record 562 | ------------------- 563 | 564 | * `POST /dns_zones/{zone_id}/dns_records` arguments: `type`,`hostname`,`value`,`ttl` - supported types: A, CNAME, TXT, MX 565 | 566 | Returns 201 on successful creation 567 | 568 | Delete a DNS record 569 | ------------------- 570 | 571 | * `DELETE /dns_zones/{zone_id}/dns_records/{id}` deletes a record 572 | 573 | Return 204 with an empty body 574 | 575 | 576 | Access Tokens 577 | ============= 578 | 579 | **Resellers only**. Issue and revoke access tokens on behalf of your users 580 | 581 | Issue an access token 582 | --------------------- 583 | 584 | * `POST /access_tokens` create an access token for a user. Supply a user: `{"user": {"email": "test@example.com", "uid": "123"}}` 585 | 586 | ```json 587 | { 588 | "id":"6da5e4827ef6ac05b123279c6ed84c3125bbba59d65facb20d20fb1e73f3c62a", 589 | "access_token":"6da5e4827ef6ac05b123279c6ed84c3125bbba59d65facb20d20fb1e73f3c62a", 590 | "user_id":"52841ed05803545ef0000001", 591 | "created_at":"2013-11-16T01:54:57Z" 592 | } 593 | ``` 594 | 595 | Revoke an access token 596 | ---------------------- 597 | 598 | * `DELETE /access_tokens/{token}` revokes the access token 599 | 600 | Returns 204 with an empty body 601 | --------------------------------------------------------------------------------