Uploading and the Thingiverse API
Uploading files through a web browser can be tricky, and doing it through a RESTful API which relies on a 3rd party storage service is downright confusing. That's why we put together this quick guide to make it a little easier for you.
The basic mechanism is as follows:
- Create or load the item that you'll be attaching the file(s) to (ie: Thing, copy, etc).
- Submit a POST to that item's files endpoint (ie: /things/#{id}/files).
- Use the parameters returned to upload to our Amazon S3 storage using an HTTP POST with multipart/form-data encoding.
See, it's not so bad. Now let's walk through the steps in detail. We'll show the full HTTP transaction in the sample requests and responses in this guide so you can see all the gory bits.
Step 1. Create or load the item that you'll be attaching to.
If you're adding files to a new item (Thing, copy, etc) you'll need to create that first using the normal API endpoints defined in our REST API Reference. If the item already exists make sure you can access it by loading it first.
Request
POST /things HTTP/1.1 Authorization: Bearer e72e16c7e42f292c6912e7710c838347ae178b4a Host: api.thingiverse.com Content-Type: application/json; charset=utf-8 Content-Length: 25 { "name":"Super Cool Thing", "category":"Art", "tags":["foo","bar","baz"], "description":"This is a test thing", "instructions":"Print and enjoy", "is_wip":true, "license":"cc" }
Response
HTTP/1.1 200 OK Date: Fri, 28 Dec 2012 01:50:33 GMT Server: Apache X-RateLimit-Remaining: 299 Cache-Control: max-age=87600, min-fresh=300 Expires: Sat, 29 Dec 2012 16:22:06 -0500 Vary: Authorization,Accept-Encoding Content-Length: 1260 Connection: close Content-Type: application/json; charset=utf-8 { "id":38514, "name":"Super Cool Thing", "thumbnail":"https://www.thingiverse.com/img/default/rendering_thumb_medium.jpg"", "url":"https://www.thingiverse.com/thing:38514", "creator":{ "id":244, "name":"potatono", "url":"https://api.thingiverse.com/users/potatono", "thumbnail":"https://thingiverse-production.s3.amazonaws.com/renders/ff/46/e6/04/1f/ApocolypseBurningMan2010_thumb_medium.jpg" }, "added":"2012-12-28T21:33:52-05:00", "modified":"2012-28-15T21:33:52-05:00", "is_published":true, "is_wip":true, "ratings_enabled":true, "like_count":1, "description":"This is a test thing", "instructions":"Print and enjoy", "license":"Attribution - Creative Commons", "files":"https://api.thingiverse.com/things/38514/files", "images":"https://api.thingiverse.com/things/38514/images", "likes":"https://api.thingiverse.com/things/38514/likes", "ancestors":"https://api.thingiverse.com/things/38514/ancestors", "derivatives":"https://api.thingiverse.com/things/38514/derivatives", "tags":"https://api.thingiverse.com/things/38514/tags", "categories":"https://api.thingiverse.com/things/38514/categories" }
Step 2. Tell Thingiverse you want to attach a file.
Use the files endpoint to tell us you want to attach a file.
Request
POST /things/38514/files HTTP/1.1 Content-Length: 33 Host: api.thingiverse.com Authorization: Bearer e72e16c7e42f292c6912e7710c838347ae178b4a Content-Type: application/json; charset=utf-8 {"filename":"SuperCoolThing.stl"}
Response
HTTP/1.1 200 OK Date: Fri, 28 Dec 2012 01:51:20 GMT X-RateLimit-Remaining: 299 Content-Length: 951 Content-Type: application/json; charset=utf-8 { "action":"https://thingiverse-staging.s3.amazonaws.com/", "fields":{ "AWSAccessKeyId":"0S2CMSXYJEXCGHRR6K82", "bucket":"thingiverse-production", "key":"uploads/84/37/86/ef/74/SuperCoolThing.stl", "acl":"public-read", "success_action_redirect":"https://api.thingiverse.com/files/111382/finalize", "policy":"eyJleHBpcmF0aW9uIjoiMjAxMi0xMi0yOVQwMTo1MToyMVoiLCJjb25kaXRpb25zIjpbeyJhY2wiOiJwdWJsaWMtcmVhZCJ9LHsiYnVja2V0IjoidGhpbmdpdmVyc2Utc3RhZ2luZyJ9LFsiZXEiLCIka2V5IiwidXBsb2Fkc1wvODRcLzM3XC84NlwvZWZcLzc0XC90ZXN0LnN0bCJdLFsiZXEiLCIkQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb25cL3NsYSJdLFsiZXEiLCIkQ29udGVudC1EaXNwb3NpdGlvbiIsIiJdLFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDEsMjYyMTQ0MDAwXSx7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjoiaHR0cDpcL1wvYXBpLnRoaW5naXZlcnNlLmRldjo4ODg4XC9maWxlc1wvODdcL2ZpbmFsaXplIn1dfQ==", "signature":"broAvG9HGPcMgGdxNFuXLUd7cSU=", "Content-Type":"application/sla", "Content-Disposition":"" } }
Step 3. Use the data from Thingiverse to upload to S3.
Use an HTTP POST to the endpoint noted in the action field and with the data contained in the other fields to send the file to S3. Note that you will need to use the HTTP encoding type multipart/form-data, which is different than the typical encoding of application/x-www-form-urlencoded. Most HTTP libraries will have some setting for this as part of their initialization but if you really need to get into the nitty-gritty see the W3C recommendation on the subject.
If you're doing an upload through a web-form or directly through javascript you may want to look at some of the new HTML5 File APIs .
Request
POST / HTTP/1.1 Host: thingiverse-production.s3.amazonaws.com Content-Type: multipart/form-data; boundary=---------------------------66289253989742337765937765 Content-Length: 12357 -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="AWSAccessKeyId" 0S2CMSXYJEXCGHRR6K82 -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="bucket" thingiverse-production -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="key" uploads/84/37/86/ef/74/SuperCoolThing.stl -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="acl" public-read -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="success_action_redirect" https://api.thingiverse.com/files/111382/finalize -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="policy" eyJleHBpcmF0aW9uIjoiMjAxMi0xMi0yOVQxOTozNDoyN1oiLCJjb25kaXRpb25zIjpbeyJhY2wiOiJwdWJsaWMtcmVhZCJ9LHsiYnVja2V0IjoidGhpbmdpdmVyc2UtcHJvZHVjdGlvbiJ9LFsic3RhcnRzLXdpdGgiLCIka2V5IiwidXBsb2Fkc1wvIl0sWyJzdGFydHMtd2l0aCIsIiRDb250ZW50LVR5cGUiLCIiXSxbInN0YXJ0cy13aXRoIiwiJENvbnRlbnQtRGlzcG9zaXRpb24iLCIiXSx7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjoiaHR0cDpcL1wvd3d3LnRoaW5naXZlcnNlLmNvbVwvdGhpbmdzXC9maW5hbGl6ZSJ9LFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLDEsMjYyMTQ0MDAwXV19 -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="signature" dyqah6pLNWvjI4AemGsvq/vjVtE= -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="Content-Type" application/sla -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="Content-Disposition" -----------------------------66289253989742337765937765 Content-Disposition: form-data; name="file"; filename="SuperCoolThing.stl" Content-Type: application/sla ... A BUNCH OF BINARY DATA ... -----------------------------66289253989742337765937765
Response
HTTP/1.1 303 See Other x-amz-id-2: QoSYmZuCUprlAs2MPJ/zQ9j+e9w9rwOqWvWaOULZE128hNcD9X/0mxBSjUPDykRw x-amz-request-id: 0AED157086A14FE5 Date: Fri, 28 Dec 2012 19:34:22 GMT ETag: "6e9a200750aafebcfecfc2f895913455" Location: https://api.thingiverse.com/files/111382/finalize/?bucket=thingiverse-production&key=uploads%2FSuperCoolThing.stl&etag=%226e9a200750aafebcfecfc2f895913455%22 Content-Length: 0 Server: AmazonS3
Step 4. Once the upload is complete, let Thingiverse know.
Send a HTTP POST to the URL given in the "success_action_redirect" parameter you received in Step 2 to let Thingiverse know to check on the file. This step isn't strictly necessary as we'll check on it automatically after awhile, but it will speed up the process of getting your file up and working.
Request
POST /files/111382/finalize HTTP/1.1 Host: api.thingiverse.com Content-Type: application/json; charset=utf-8 Content-Length: 0 Authorization: Bearer e72e16c7e42f292c6912e7710c838347ae178b4a
Response
HTTP/1.1 200 OK Date: Fri, 28 Dec 2012 01:53:35 GMT X-RateLimit-Remaining: 299 Content-Length: 951 Content-Type: application/json; charset=utf-8 { "id": 111959, "name": "SuperCoolThing.stl", "url": "https://www.thingiverse.com/download:111959" }
That's it!
Once you've finalized your upload it will just take Thingiverse a few moments to process it before it goes live. If you're uploading an image or a file that we're able to render into an image, you may want to check back periodically to see if we've completed all the processing.