Introduction

The PowerTool Safe API uses REST. Our API has predictable URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard status codes.

All requests must be made over HTTPS. Plain HTTP requests will fail.

Your developer account includes two keys: sandbox and production. The key serves as both your authentication and the selector for which system your request is routed to. The sandbox does not affect your live data or interact with other networks.

Customers must opt in before you can add or read their tools and receipts. See Customer Access below.

API Keys

The API uses keys to authenticate requests. You can view and manage your API keys in the Dashboard.

Test keys have the prefix test_ and live keys have the prefix live_. Keep your keys secure. They would allow someone to create accounts on your behalf and make updates to your customers' tools. For instance, do not make JavaScript calls to the API from your client browser code, as this would make your key visible to any user with the ability to view the page source. You definitely don't want to share them on GitHub!

Authentication is performed on every request by passing your key as a parameter named key. Requests with no key return 401. Requests with an unknown key, or a key for a developer account that has not yet been activated, return 403.

Error Handling

The API uses standard status codes for error handling. Error responses include an error attribute with a short message explaining the problem.

200 - OK
No errors.
400 - Bad Request
A required field is missing, or the item being added already exists. Check the error attribute for details.
401 - Unauthorized
No API key was provided.
402 - Request Failed
The payload was missing or could not be parsed, or it referred to a customer, brand, or model that could not be found. Check the error attribute.
403 - Forbidden
The API key is not valid, the developer account is not activated, or the customer has not opted in to your company.
404 - Not Found
The requested customer does not exist.
429 - Too Many Requests
Too many requests hit the API too quickly. The API is throttled to 120 calls per minute. Contact us if you need more.
500, 502, 503, 504 - Server Errors
Something went wrong on the server. Don't worry, we monitor the error logs and we'll get it resolved.

Verbs and Parameters

Verbs such as GET and POST determine the action to take on an endpoint.

Parameters are passed as a JSON document in a single parameter named payload. Images are passed as Base64 strings within the payload. The one piece of data that is not part of the payload is the API key, which is always passed in its own parameter named key.

When the attributes of a documented payload are indented, that indicates a nested object or array within the attribute above.

For GET requests, send payload and key as URL query parameters, as in /some_call?payload={...}&key=test_mykey. For POST requests, send them as form fields in the request body. Remember to URL-encode the payload.

Customer Access

A customer's tools and receipts belong to the customer, so a customer must opt in to your company before you can add or read them.

  • When you create a customer with POST /customer, that customer is opted in to your company automatically. PowerTool Safe sends the customer an email inviting them to activate their new account.
  • If the customer already has a PowerTool Safe account, POST /customer returns 402 and you cannot change their details. The customer must grant your company access from the Third Party Access page inside their PowerTool Safe account before you can add tools or receipts for them.
  • Until a customer has opted in, POST /transaction returns 403 with an empty body, and the GET endpoints return an empty list.
  • You can only read the tools and receipts that were created with your key. Items the customer added themselves, or that another developer added, are not returned.

Endpoints

Preface all endpoint requests with https://powertoolsafe.com/api/v1. As we move to future versions of the API the version number will change, but calls to a previous version will be supported.

Customer

A customer is an end user in the PowerTool Safe system. They are identified by an email address.

To process a transaction for a customer, a typical flow would be:

  • 1 - Check to see if the customer exists with GET /customer/{email}
  • 2 - If it doesn't exist (a 404 status is returned), add it with POST /customer
  • 3 - Add the tools and receipts for that customer with POST /transaction

Payload Attributes

  • email - The email address of the user.
  • type - The type of the user (construction, homeowner).
  • name - The full name of the user.
  • company - The company name for users of type construction (optional).
  • phone - The phone number (optional).
  • billing
    • address1 - billing street address
    • address2 - billing address additional line (send an empty string if there is none)
    • city - billing address city
    • state - billing address state
    • postal_code - billing address postal code
  • shipping
    • address1 - shipping street address
    • address2 - shipping address additional line (send an empty string if there is none)
    • city - shipping address city
    • state - shipping address state
    • postal_code - shipping address postal code

Addresses are currently recorded as United States addresses.

Endpoints

GET /customer/{email} Returns
{
    "email": "thecustomer@powertoolsafe.com",
    "yours": true,
    "types": ["construction"]
}
Returns 404 if the customer is not found; you can then POST and create a new one. "yours" indicates that this is a customer you created. "types" lists the account types the customer has.
POST /customer Payload
{
    "email": "thecustomer@powertoolsafe.com",
    "type": "construction",
    "name": "Power Tool",
    "company": "Big Construction Inc",
    "phone": "406-555-1212",
    "billing": {
        "address1": "123 Any Lane",
        "address2": "Apt 2",
        "city": "Bozeman",
        "state": "MT",
        "postal_code": "59718"
    },
    "shipping": {
        "address1": "123 Any Lane",
        "address2": "Apt 2",
        "city": "Bozeman",
        "state": "MT",
        "postal_code": "59718"
    }
}
Returns
{
    "email": "thecustomer@powertoolsafe.com"
}
Creates the customer, opts them in to your company, and emails them an invitation to activate their account. Returns 402 if the customer already exists, since you cannot update an existing customer's attributes. Returns 402 if the payload is missing, is not valid JSON, or has no email.

Examples

$ curl -X GET "https://powertoolsafe.com/api/v1/customer/thecustomer@powertoolsafe.com?key=test_asdsdf89sdm2tsdfg"

$ curl -X POST https://powertoolsafe.com/api/v1/customer \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"email":"thecustomer@powertoolsafe.com","type":"construction","name":"Power Tool","company":"Big Construction Inc","phone":"406-555-1212","billing":{"address1":"123 Any Lane","address2":"Apt 2","city":"Bozeman","state":"MT","postal_code":"59718"},"shipping":{"address1":"123 Any Lane","address2":"Apt 2","city":"Bozeman","state":"MT","postal_code":"59718"}}'

Transaction

A transaction provides the capability of adding and querying receipts and tools for a customer.

The transaction consists of a receipt and then a list of tools from that receipt.

The brand of each tool must already exist in PowerTool Safe; an unknown brand returns 402. Use the Brand endpoints below to look up or add a brand. If a model is not yet known for that brand, PowerTool Safe researches it and adds it automatically.

Payload Attributes

  • email - The email address of the customer.
  • type - The type of the customer (construction, homeowner).
  • receipt - A single receipt for this transaction
    • date - the date on the receipt
    • total - the total amount on the receipt
    • description - any text to describe the receipt (not required)
    • invoice - the invoice number of the receipt
    • sold_by - text to indicate the sales person (not required)
    • images - array of any number of pages (may be empty). If any pages are sent, page 1 must be included.
      • page - integer page number
      • encoded_image - base64 encoding of the image
  • tools - array of any number of tools
    • brand - Brand/Manufacturer of the tool
    • model - Model of the tool
    • serial_number - Serial number on the tool (not required)
    • purchase_price - Price of the tool according to the receipt (not required)
    • is_new - 1 if new purchase, 0 if used (not required, defaults to 1)

Endpoints

POST /transactionPayload
{
    "email": "thecustomer@powertoolsafe.com",
    "type": "construction",
    "receipt": {
        "date": "2021-01-15",
        "total": "933.23",
        "description": "online sale",
        "invoice": "100221",
        "sold_by": "PB",
        "images": [
            { "page": 1, "encoded_image": "aWpqWtSW0OXLkSEHRqSAIrFmzhm9/+9s0NzdP73vLKZwPTPD3H3cRSoOczaDL" },
            { "page": 2, "encoded_image": "Dz30ECtXrdXHq1ClOnz49657y8nJWtbTwyCOP4Pf778ifitx2MqYQjUb5/PPP" }
        ]
    },
    "tools": [
        { "brand": "DeWalt", "model": "DW2400", "serial_number": "2220022", "purchase_price": "344.22", "is_new": 1 },
        { "brand": "DeWalt", "model": "DW2402", "purchase_price": "344.22", "is_new": 0 }
    ]
}
Returns
{
    "email": "thecustomer@powertoolsafe.com",
    "type": "construction",
    "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
    "tools": [
        { "brand": "DeWalt", "model": "DW2400", "tool_uuid": "cacedc28-e7a9-4f90-96b3-5b570fa5bdd7" },
        { "brand": "DeWalt", "model": "DW2402", "tool_uuid": "d86cc17a-5112-42f2-9881-5d911566a020" }
    ]
}
Returns 400 if the receipt date, total, or invoice is missing, or if images were sent without page 1. Returns 402 if the customer or customer type is not found, or a brand is unknown. Returns 403 with an empty body if the customer has not opted in to your company.
POST /transaction/toolsPayload - update serial numbers on tools you created
{
    "tools": [
        { "tool_uuid": "cacedc28-e7a9-4f90-96b3-5b570fa5bdd7", "serial_number": "5738292" },
        { "tool_uuid": "d86cc17a-5112-42f2-9881-5d911566a020", "serial_number": "3223332" }
    ]
}
Returns
{
    "tools_updates": 2
}
Returns 402 if the tools list, a tool_uuid, or a serial_number is missing. Returns 403 if a tool was not created with your key or its owner has not opted in.
GET /transaction/toolsPayload - email and type, plus any combination of the other attributes to narrow the search. Returns all matching tools.
{
    "email": "thecustomer@powertoolsafe.com",
    "type": "construction",
    "brand": "DeWalt",
    "model": "DW2400",
    "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
    "tool_uuid": "cacedc28-e7a9-4f90-96b3-5b570fa5bdd7"
}
Returns
{
    "search": {
        "email": "thecustomer@powertoolsafe.com",
        "type": "construction",
        "brand": "DeWalt",
        "model": "DW2400",
        "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
        "tool_uuid": "cacedc28-e7a9-4f90-96b3-5b570fa5bdd7"
    },
    "tools": [
        {
            "brand": "DeWalt",
            "model": "DW2400",
            "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
            "tool_uuid": "cacedc28-e7a9-4f90-96b3-5b570fa5bdd7"
        }
    ]
}
Returns 402 if email or type is missing, or the customer is not found. Returns an empty tools list if nothing matches or the customer has not opted in.
GET /transaction/receiptsPayload - email and type, plus any combination of the other attributes to narrow the search. Returns all matching receipts.
{
    "email": "thecustomer@powertoolsafe.com",
    "type": "construction",
    "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
    "date": "2021-01-15",
    "total": "933.23",
    "description": "online sale",
    "invoice": "100221",
    "sold_by": "PB"
}
Returns
{
    "search": {
        "email": "thecustomer@powertoolsafe.com",
        "type": "construction",
        "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
        "date": "2021-01-15",
        "total": "933.23",
        "description": "online sale",
        "invoice": "100221",
        "sold_by": "PB"
    },
    "receipts": [
        {
            "receipt_id": "62b19b0c-8469-43cc-aaf0-612bf5b6af8e",
            "date": "2021-01-15",
            "date_added": "2021-12-15T18:22:41.000000Z",
            "total": "933.23",
            "description": "online sale",
            "invoice": "100221",
            "sold_by": "PB",
            "tools": [
                ["DeWalt", "DW2400", "cacedc28-e7a9-4f90-96b3-5b570fa5bdd7"],
                ["DeWalt", "DW2402", "d86cc17a-5112-42f2-9881-5d911566a020"]
            ]
        }
    ]
}
Each entry in "tools" is [brand, model, tool_uuid]. Returns 402 if email or type is missing, or the customer is not found. Returns an empty receipts list if nothing matches or the customer has not opted in.

Examples

$ curl -X POST https://powertoolsafe.com/api/v1/transaction \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"email":"thecustomer@powertoolsafe.com","type":"construction","receipt":{"date":"2021-01-15","total":"933.23","description":"online sale","invoice":"100221","sold_by":"PB","images":[{"page":1,"encoded_image":"aWpqWtSW0OXLkSEHRqSAIrFmzhm9/+9s0NzdP73vLKZwPTPD3H3cRSoOczaDL"},{"page":2,"encoded_image":"Dz30ECtXrdXHq1ClOnz49657y8nJWtbTwyCOP4Pf778ifitx2MqYQjUb5/PPP"}]},"tools":[{"brand":"DeWalt","model":"DW2400","serial_number":"2220022","purchase_price":"344.22","is_new":1},{"brand":"DeWalt","model":"DW2402","purchase_price":"344.22","is_new":0}]}'

$ curl -X POST https://powertoolsafe.com/api/v1/transaction/tools \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"tools":[{"tool_uuid":"cacedc28-e7a9-4f90-96b3-5b570fa5bdd7","serial_number":"5738292"},{"tool_uuid":"d86cc17a-5112-42f2-9881-5d911566a020","serial_number":"3223332"}]}'

$ curl -G https://powertoolsafe.com/api/v1/transaction/tools \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"email":"thecustomer@powertoolsafe.com","type":"construction","brand":"DeWalt","model":"DW2400"}'

$ curl -G https://powertoolsafe.com/api/v1/transaction/receipts \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"email":"thecustomer@powertoolsafe.com","type":"construction","invoice":"100221"}'

Brands and Models

Brands and models are shared across PowerTool Safe. Use these endpoints to check how a brand or model is spelled in our catalog before sending a transaction, to look up a model by UPC, or to add a brand or model we do not have yet. All four endpoints use GET.

Name searches match exactly unless the name contains a % wildcard, as in "DeW%". Searches return at most 100 results per call; use start and end to page through more.

Some catalog entries are aliases of another entry. When that is the case the map_to attributes identify the entry we treat as the canonical one.

Endpoints

GET /transaction/brand/getPayload
{
    "name": "DeW%",
    "start": 0,
    "end": 100
}
Returns
[
    { "id": "1f0f3a2e-9c7a-4d1b-9e2d-0b3f0f3c9a11", "name": "DeWalt", "map_to": null, "map_to_name": null }
]
name is required; start and end are optional. Returns 402 if name is missing.
GET /transaction/brand/addPayload
{
    "name": "Acme Tools"
}
Returns
{
    "id": "7c2d4e9a-3b1f-4a6e-8d2c-5e1f9b0a7c33",
    "name": "Acme Tools"
}
Returns 400 if the brand already exists. Returns 402 if name is missing.
GET /transaction/model/getPayload - either brand_name and model_name, or upc
{
    "brand_name": "DeWalt",
    "model_name": "DW24%",
    "start": 0,
    "end": 100
}
{
    "upc": "885911245883"
}
Returns
[
    {
        "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
        "brand_name": "DeWalt",
        "model_name": "DW2400",
        "upc": "885911245883",
        "map_to": null,
        "map_to_brand_name": null,
        "map_to_model_name": null,
        "map_to_upc": null
    }
]
Returns 402 if neither upc nor both brand_name and model_name are supplied.
GET /transaction/model/addPayload
{
    "brand_id": "1f0f3a2e-9c7a-4d1b-9e2d-0b3f0f3c9a11",
    "name": "DW2400",
    "part_name": "Oscillating Multi-Tool",
    "upc": "885911245883",
    "upc_url": "https://example.com/upc/885911245883",
    "msrp": "129.00",
    "msrp_url": "https://example.com/dw2400",
    "warranty_quantity": 3,
    "warranty_units": "years",
    "warranty_url": "https://example.com/warranty",
    "manual_url": "https://example.com/dw2400/manual.pdf",
    "map_to": null
}
Returns
{
    "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "name": "DW2400",
    "part_name": "Oscillating Multi-Tool",
    "brand_id": "1f0f3a2e-9c7a-4d1b-9e2d-0b3f0f3c9a11",
    "msrp": "129.00",
    "msrp_url": "https://example.com/dw2400",
    "upc": "885911245883",
    "upc_url": "https://example.com/upc/885911245883",
    "warranty_quantity": 3,
    "warranty_units": "years",
    "warranty_url": "https://example.com/warranty",
    "manual_url": "https://example.com/dw2400/manual.pdf",
    "map_to": null
}
brand_id (the id returned by the brand endpoints), name, and part_name are required; the rest are optional. map_to, when used, is the id of the model this one is an alias of. Returns 400 if the model already exists for that brand. Returns 402 if a required field is missing or the brand or map_to model is not found.

Examples

$ curl -G https://powertoolsafe.com/api/v1/transaction/brand/get \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"name":"DeW%"}'

$ curl -G https://powertoolsafe.com/api/v1/transaction/model/get \
    -d key=test_asdsdf89sdm2tsdfg \
    --data-urlencode 'payload={"upc":"885911245883"}'