» Introduction
» Materials catalog
» Uploading a product
» Making a product
» Updating a product
» Order history
» Test users
» Debugging
We are loosely following REST principles in that all requests are either GET or POST. Requests are made over SSL. This ensures all information you pass to the API is encrypted, including the URL. To keep things as simple as possible, data is passed to the API as URL encoded parameters.
Include your Simple access keys as URL Parameters with each API call to be granted access your Personal Factory. These keys are found on your App's detail page.
app_key=abcdefgh&user_access_key=stuvwxyz
We're also using the current industry standard of OAuth to grant applications access to user accounts. When you register your application with ponoko.com it will be granted immediate access to your user account to make it easy for you to get started.
At this stage your application can only access products it adds to a user's account. Your application cannot access anything the user has created themselves.
All responses are in JSON. See http://json.org/ for more information.
We identify all objects through the API uniquely using long strings called 'keys'.
Anything you create via the API has an associated reference field ('ref'). You can use this to store your own unique reference for the created object. The field allows for a 255 character string.
You can use your reference instead of our 'key' wherever you see a 'key' variable in the PATH of an API call or as a parameter.
Unless stated otherwise, you need to fill in all the parameters listed for an object when you create it. If you miss any, you'll get an error response instead of a created object.
Updating objects
You don't have to pass in all data fields when updating an object's data, such as a product name. Only the passed in fields will be changed.
The Curl examples are constructed with the “-d” or “-F” parameters for passing data. This makes them more readable. We've left out the Simple access authentication keys in these examples ‒ you'll need to include your own like this:
-d "app_key=abcdefgh" \
-d "user_access_key=stuvwxyz" \
Not used Curl before? This is a handy reference resource: http://linux.about.com/od/commands/l/blcmdl1_curl.htm
Arrays of information are passed in the URL parameters like this:
-d “products[][key]=1234” \
-d “products[][quantity]=1” \
-d “products[][key]=5678” \
-d “products[][quantity]=5” \
Note the empty square brackets? This is what defines the array. The order of the keys is important too, so make sure you keep to the order shown in this document.
If a request fails, error information explaining the reason will appear in the JSON response like this:
{
"error": {
"message": "Bad Request. Error processing design file(s).",
"errors": [
{
"name": "broken_design.stl",
"error_code": "unfixable_mesh_errors",
"type": "design_processing"
}
],
<< extra info >>
}
}
"errors" is optionally returned when there is more than one problem, such as with multiple designs.
The << extra info >> above is for things such as key, ref and/or file names so you can trace the error more easily. See API error responses and Design file warnings and errors for more information.
We have a sandbox server for you to test your application:
https://sandbox.ponoko.com/services/api/v2
Once we've granted your application live access, you'll need to switch to using this url:
http://www.ponoko.com/services/api/v2
You can log into the sandbox server with your usual email address and password here:
https://sandbox.ponoko.com/account/login
Note: this is a cut down version of the live website focused on App development.
Don't forget to checkout the API reference section which contains a complete listing of supported countries, order events, design file errors and their meanings etc...
You must specify which material is to be used when you make a design with ponoko.com. In order to do this, you'll first need to download the materials catalog from your preferred making node.
The 'find a node' feature gives you a list of available making nodes the associated user account can access.
GET /nodes
No parameters.
curl https://sandbox.ponoko.com/services/api/v2/nodes
Response example
{"nodes": [{"key": "2413",
"name": "Ponoko USA",
"materials_updated_at": "2011/01/01 12:00:00 +0000"}, ...]}
The 'materials_updated_at' field lets you know when that node's materials catalog was last changed. This means you can cache the catalog easily and only download it again when it's updated.
This feature returns the entire materials catalog for a given node.
GET /nodes/material-catalog/<< node key >>
No parameters.
curl https://sandbox.ponoko.com/services/api/v2/nodes/material-catalog/2413
{"node_key": "1234",
"materials": [{"key": "1234",
"name": "cardboard",
"type": "sheet",
"updated_at": "2011/01/01 12:00:00 +0000",
<type specific data>}, ...]}
Orders are placed for a product which is a collection of design files. Materials used to make the product can only be sourced from a single node. In other words, you can't use wood from one node and plastic from another when defining the product. Once created, a product will always 'know' its making cost, even when designs and materials are changed.
Products are added to the user's account you are accessing via OAuth.
This is the preferred way to create products as it combines all information, including all designs and their chosen materials, into the single API call.
POST /products
curl -F "name=Lamp"\
-F "notes=some%20long%20note%20about%20the%20design" \
-F "ref=2413" \
-F "designs[][ref]=42" \
-F "designs[][file_name]=teapot.stl" \
-F "designs[][uploaded_data]=@teapot.stl" \
-F "designs[][quantity]=1" \
-F "designs[][material_key]=2413" \
-F "designs[][units]=mm" \
-F "designs[][ref]=11b" \
-F "designs[][file_name]=ruler.eps" \
-F "designs[][uploaded_data]=@ruler.eps" \
-F "designs[][quantity]=2" \
-F "designs[][material_key]=2413" \
https://sandbox.ponoko.com/services/api/v2/products
Note: this example is passing two design files - the formatting of the parameters is important and continues the same way for any number of designs.
'Units' is only required for STL and WRL file formats.
{"product": {"key": "1234",
"ref": "4321",
"node_key": "1234",
"name": "tea pot,
"notes": "has a special non-drip spout",
"created_at": "2011/01/01 12:00:00 +0000",
"updated_at": "12011/01/01 12:00:00 +0000",
"locked?" :"false",
"materials_available?": true,
"designs": [{"key": "1234",
"ref": "4321",
"created_at": "2011/01/01 12:00:00 +0000",
"updated_at": "2011/01/01 12:00:00 +0000",
"size": 9999,
"file_name": "teapot.stl",
"units": "mm",
"quantity": 1,
"content_type": "application/postscript",
"material_key": "1234",
"unmakable_materials": ["4321"],
"make_cost": {"currency": "USD",
"making": "56.78",
"materials": "56.78",
"total": "56.78"}}],
"design_images": [{"file_name": "teapot.stl.png"}],
"total_make_cost": {"currency": "USD",
"making": "56.78",
"materials": "56.78",
"hardware": "0.0",
"total": "113.56"},
"urls": {"view": "http://www.ponoko.com/products/show/1234",
"make": "http://www.ponoko.com/make/new/1234"}}
• locked? - products are 'locked' while they are being made and this is reflected in this field. A product cannot be changed while it is locked.
• materials_available? - this becomes 'false' when a material used in a product is no longer available.
• unmakable_materials - lists materials that a 3D design can't be made with.
A product will not be created if there are any errors when uploading. Generally, this means the design files contain problems which make them unprintable. The error response you see will be the same as for users of www.ponoko.com, see Design file warnings and errors for more information.
Designs can be added without a material specified, but for a product to be ordered at least one design must have a material.
When accessing a user's Ponoko account with OAuth the URLS fields enable your app to send the user directly to the viewing or making pages on the ponoko.com website for that product.
See Supported file formats for a list of supported file formats.
Once you have created at least one product, you can use this function to get a list of them.
GET /products
No parameters
curl --get https://sandbox.ponoko.com/services/api/v2/products
{"products": [{"key": "1234",
"ref": "4321",
"name": "tea pot",
"created_at": "2011/01/01 12:00:00 +0000",
"updated_at": "2011/01/01 12:00:00 +0000"} ...]}
You can get full details for a product by entering the product key.
GET /products/<< product key >>
No parameters
curl --get http://sandbox.ponoko.com/services/api/v2/products/2413
See 'Create the whole product in one step' above.
Placing an order for a product is a two step process. First you need to 'ask' the product what the shipping options are for a given address, select one and then pass that back when creating the order.
You can only place orders for products belonging to your user account and only if you've pre- registered a credit card (or other payment option) with us. We charge your credit card when each order is placed successfully.
If the materials for the product(s) are made up of multiple making methods (e.g. laser cutting and 3D printing), they will be priced and shipped as separate deliveries.
Sandbox accounts have full access to this functionality without your needing to register a credit card first.
Just pass in products, quantities and the destination address. You'll then get back the available shipping options and costing. The costing is only valid for a short period of time (approx 60 minutes).
GET /orders/shipping-options
Note: 'country' needs to be the full country name ‒ no abbreviations.
See Country list for a full list of supported countries.
curl -d “products[][key]=1234” \
-d “products[][quantity]=1” \
-d “quantity=1” \
-d "delivery_address[address_line_1]=27%20Dixon%20Street" \
-d "delivery_address[address_line_2]=Te%20Aro"
-d "delivery_address[city]=Wellington" \
-d "delivery_address[state]=na" \
-d "delivery_address[zip_or_postal_code]=6021" \
-d "delivery_address[country]=New%20Zealand" \
--get https://sandbox.ponoko.com/services/api/v2/orders/shipping-options
{"shipping_options": {"products": [{"key": "1234",
"ref": "4321",
"quantity": 1}...],
"quantity": 1,
"currency": "USD",
"options": [{"code": "ups_ground",
"name": "UPS Ground",
"price": "56.78"}...]}}
Once you have a list of shipping options, select one of them and pass that into the 'shipping_option_code' field. This will create an order and place it into the production queue for it to be made and shipped.
POST /orders
Note: if you omit the 'billing_address', the 'delivery_address' is used in its place.
curl -d "ref=42" \
-d “products[][key]=1234” \
-d “products[][quantity]=1” \
-d “products[][key]=5678” \
-d “products[][quantity]=5” \
-d "shipping_option_code=ups" \
-d "delivery_address[first_name]=Bob" \
-d "delivery_address[last_name]=Builder" \
-d "delivery_address[address_line_1]=27%20Dixon%20Street" \
-d "delivery_address[address_line_2]=Te%20Aro" \
-d "delivery_address[city]=Wellington" \
-d "delivery_address[state]=na" \
-d "delivery_address[zip_or_postal_code]=6021" \
-d "delivery_address[country]=New%20Zealand" \
-d “delivery_address[phone_number]=1234567890” \
https://sandbox.ponoko.com/services/api/v2/orders
{"order": {"key": "1234",
"ref": "4321",
"products": [{"key": "1234",
"ref": "4321",
"quantity": 1}...],
"node_key": "1234",
"shipped": "false",
"created_at": "2011/01/01 12:00:00 +0000",
"updated_at": "2011/01/01 12:00:00 +0000",
"cost": {"currency": "USD",
"making": "56.78",
"materials": "56.78",
"shipping": "56.78",
"hardware": "0.00",
"total": "56.78"},
"shipping_option_code": "ups_ground",
"tracking_numbers": ["xxx-yyy" ...],
"events": [{"name": "design_checked",
"completed_at": "2011/01/01 12:00:00 +0000"} ...]}}
See Order events for the complete list.
This is a lightweight call for checking an orders status. It simply shows if the order has shipped or not and lists the events which have been completed.
GET /orders/status/<< order key >>
No parameters
curl --get https://sandbox.ponoko.com/services/api/v2/orders/status/2413
{"order": {"key": "1234",
"ref": "4321",
"shipped": "false",
"events": [{"name": "design_checked",
"completed_at": "2011/01/01 12:00:00 +0000"} ...],
"last_successful_callback_at": "2011/01/01 12:00:00 +0000",
"shipping_option_code": "ups_ground",
"tracking_numbers": ["xxx-yyy" ...]}}
When a callback is registered against your application, this same information will be sent to your registered callback URL. This happens whenever there is a change to the order.
Note: our preference is that you rely on the callback (below) for order status updates rather than continually polling our API.
A provided callback URL will be POSTed to whenever an event occurs for an order. For security reasons, we recommend your URL contains a secret key as a URL parameter. The callback can be made over either HTTP or HTTPS.
Your website must return with the HTTP 200 response code to indicate the call was successful, otherwise the API will try again later. When failure does occur the callback will be tried again with an increasing delay between attempts. Callback attempts will eventually stop 2 days after the last event occurs for an order or after a 200 response is received.
In our job processing back-end, operators click through as they reach set events in the making process - such as 'materials ordered', 'designs checked' etc. Sometimes they process a bunch of these all at once. For this reason, we have a delay of several minutes before callbacks are sent. This means your server won't necessarily receive one callback for each event, so several events may have occurred between callbacks.
The callback includes a 'last_successful_callback_at' field so you can easily determine what events have occurred subsequently.
The following is posted as JSON to an 'order' key:
{"key": "1234",
"ref": "4321",
"shipped": "false",
"events": [{"name": "design_checked",
"completed_at": "2011/01/01 12:00:00 +0000"} ...],
"last_successful_callback_at": "2011/01/01 12:00:00 +0000",
"shipping_option_code": "ups_ground",
"tracking_numbers": ["xxx-yyy" ...]}
This is exactly the same as the response to the /orders/status call above and includes an array of all the completed events for the order.
Nobody actually makes products ordered on the sandbox server, so we have a special API call to pretend this is happening. This will advance the order through the various stages of making, including sending callbacks at each stage.
GET /orders/trigger-next-event/<< order key >>
No parameters
curl --get https://sandbox.ponoko.com/services/api/v2/orders/trigger-next-event/1234
{"order": {"key": "1234",
"ref": "4321",
"shipped": "false",
"events": [{"name": "design_checked",
"completed_at": "2011/01/01 12:00:00 +0000"} ...]}}
Note: this API call is only available on the sandbox server and there can be a delay of several minutes between this API call and the callback being triggered.
Once created, products can be updated – for example, replacing a design or changing the material it's made from. You can even include additional designs.
You can update a product by changing its main details, including your ref field.
POST /products/<< product key >>/update
Parameters
• ref
• name
• description
See 'Create the whole product in one step' above.
You can add subsequent designs once a product has been created.
POST /products/<< product key >>/add-design
• ref
• file_name
• uploaded_data
• quantity
• material_key
See 'Create the whole product in one step' above.
You can replace a design's file or simply change the material.
POST /products/<< product key >>/update-design/<< design key >>
• ref
• file_name
• uploaded_data
• quantity
• material_key
Note: you can only change the file_name when uploading a new design file.
See 'Create the whole product in one step' above.
You can delete individual designs from a product. However products are only valid while they have designs and you can't delete the last design from a product.
POST /products/<< product key >>/delete-design/<< design key >>
No parameters
See 'Create the whole product in one step' above.
You can add photos of the product.
POST /products/<< product key >>/design-images
curl -F "design_images[][uploaded_data]=@my_image.jpg" \
-F "design_images[][default]=1" \
https://sandbox.ponoko.com/services/api/v2/products/2413/design-images
See 'Create the whole product in one step' above. The design image section within the product response will be as follows
{"design_images": [{"filename": "my_image.jpg",
"default": true}]}
Get the photos of the product.
GET /products/<< product key >>/design-images/download?filename=<< file name >>
• filename
curl --get https://sandbox.ponoko.com/services/api/v2/products/2413\ /design-images/download?filename=my_image.jpg
The response will be the raw image data.
Remove a photo from a product.
GET /products/<< product key >>/design-images/destroy?filename=<< file name >>
• file name
curl --get https://sandbox.ponoko.com/services/api/v2/products/2413\ /design-images/destroy?filename=my_image.jpg
See 'Create the whole product in one step' above.
You can add assembly instructions to the product.
POST /products/<< product key >>/assembly-instructions
curl -d "assembly_instructions[][uploaded_data]=@instructions.pdf" \
https://sandbox.ponoko.com/services/api/v2/products/2413/assembly-instructions
See 'Create the whole product in one step' above.The assembly instructions section within the product response will be as follows
{"assembly_instructions": [{"filename": "instructions.pdf"}]}
Get the assembly instructions for the product.
GET /products/<< product key >>/assembly-instructions/download?filename=<< file name >>
• file name
curl --get https://sandbox.ponoko.com/services/api/v2/products/2413\ /assembly-instructions/download?filename=instructions.pdf
The response will be the raw file.
Remove an assembly instructions file from a product.
GET /products/<< product key >>/assembly-instructions/destroy?filename=<< file name >>
• file name
curl --get https://sandbox.ponoko.com/services/api/v2/products/2413\ /assembly-instructions/destroy?filename=instructions.pdf
See 'Create the whole product in one step' above.
You can add hardware to your product.
POST /products/<< product key >>/hardware
• sku
• quantity
curl -d "sku=GPS-08254" \
-d "quantity=3" \
https://sandbox.ponoko.com/services/api/v2/products/2413/hardware
See 'Create the whole product in one step' above. The hardware section within the product response will be as follows
{"hardware": [{"sku": "GPS-08254",
"name": "Widget",
"quantity": "3",
"weight": "0.1kg",
"currency": "USD",
"cost": "9.99",
"total_cost": "29.97"}]}
You can change the hardware quantity.
POST /products/<< product key >>/hardware
• sku
• quantity
curl -d "sku=GPS-08254" \
-d "quantity=3" \
https://sandbox.ponoko.com/services/api/v2/products/2413/hardware
See the 'Add hardware' response
You can remove hardware from your product.
POST /products/<< product key >>/hardware
• sku
curl -d "sku=GPS-08254" \
https://sandbox.ponoko.com/services/api/v2/products/2413/hardware
See 'Create the whole product in one step' above.
You can delete products which have not yet been made.
POST /products/delete/<< product key >>
No parameters
{"product_key": "1234", "deleted": true}
You can pull up a list of orders once you have created at least one.
GET /orders
No parameters
curl --get https://sandbox.ponoko.com/services/api/v2/orders
{"orders": [{"key": "1234",
"ref": "4321",
"shipped": true,
"created_at": "2011/01/01 12:00:00 +0000",
"updated_at": "2011/01/01 12:00:00 +0000"} ...]}
You can get the full details for an order once you have its key.
GET /orders/<< order key >>
No parameters
curl --get https://sandbox.ponoko.com/services/api/v2/orders/2413
See 'Order your product' above.
These API calls allow you to manage test user accounts on the Ponoko Sandbox server for use by Apps using OAuth authentication. You can log into them here.
The call to create a user is very simple and requires no paramaters.
POST /users
No parameters.
curl https://sandbox.ponoko.com/services/api/v2/users
{
"sandbox_only": true,
"user": {
"password": "123",
"email": "123@sandbox.ponoko.com"
}
}
We generate a random password for your test user accounts and use it as part of the email address. Use the below API call to recover forgotten passwords/email addresses.
You can create up to a maximum of 3 users.
You can pull up a list of your test user accounts, this includes their passwords.
GET /users
No parameters.
curl --get https://sandbox.ponoko.com/services/api/v2/users
{
"sandbox_only": true,
"users": [
{
"password": "123",
"email": "123@sandbox.ponoko.com"
},
{
"password": "456",
"email": "456@sandbox.ponoko.com"
},
{
"password": "789",
"email": "789@sandbox.ponoko.com"
}
]
}
This gives you access to a log of your requests made to the API and their responses.
GET logs/requests
• max
curl -d "max=20" --get https://sandbox.ponoko.com/services/api/v2/logs/requests
{
"requests": [
{
"response": {
"nodes": [
{
"key": "2413",
"name": "Ponoko USA",
"materials_updated_at": "2011/01/01 12:00:00 +0000"
}
]
},
"created_at": "2012/01/01 12:00:00 +0000",
"method": "get",
"path": "/services/api/v2/nodes",
"params": {
},
"http_status": 200
}
]
}
The optional 'max' parameter can be any value from 1 to 20 and will only return log entries less than 24 hours old.