Loading

Uploading with 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:

  1. Create or load the item that you'll be attaching the file(s) to (ie: Thing, copy, etc).
  2. Submit a POST to that item's files endpoint (ie: /things/#{id}/files).
  3. Use the parameters returned to upload to our Amazon S3 storage using an HTTP POST with multipart/form-data encoding.
  4. Once complete, hit the success action endpoint to let Thingiverse know to check on the file.

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":"http://www.thingiverse.com/img/default/rendering_thumb_medium.jpg"",
        "url":"http://www.thingiverse.com/thing:38514",
        "creator":{
          "id":244,
          "name":"potatono",
          "url":"https://api.thingiverse.com/users/potatono",
          "thumbnail":"http://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.

Watch out! Make sure you send the parameters in the same order you received them otherwise S3 may refuse to accept them.
Also, do not set the Authorization header that you use for Thingiverse.

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.

Watch out! Make sure you have the Authorization header set for this request

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": "http://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.

Top