RepairShopr REST API - Build custom extensions/apps/addons

RepairShopr API Documentation

RepairShopr uses a very simple HTTP REST API.

Here is a little light reading material that might help get you up to speed quickly;


Our API has a very simple authorization, a user-level API key passed as a param.

You can go get your API key on your profile page;

There you go:

Obtaining a new key

Just click that little 'reset' link on the profile page and a new key will be generated. It will immediately block access to the current/old key.

Rate Limits

This is subject to change but currently we'll allow 120 requests per minute for each account before responding with an error.

Request Format

We return all data as json. When sending data in to us you can use regular form encoding or set the content type to json and use it in the body.

You can send a simple HTTP GET to many endpoints, just pass the api_key parameter like so;


All the endpoints are paginating. You can add a param like &page=2 to the request to get to the other pages. Here are the defaults;
  • Customers: 100
  • Invoices: 50
  • Leads: 20
  • Tickets: 100


We are exposing endpoints as-needed, there are a handful that have been in production for a while now. Here you go!

User /api/v1

  • me GET /me
    A helper endpoint to show you who is logged in and state their permissions. It returns something like this:
  • login POST /sign_in
    returns the same user object from above
    valid params: :email, :password

Leads /api/v1

  • index GET /leads.json
  • show GET /leads/:id
  • new GET /leads/new (instructions)
  • create POST /leads
For some extra things you can do with leads, including using PHP, please click here!

Valid parameters
:first_name, :last_name, :email, :phone, :mobile, :created_at, :updated_at,
:address, :city, :state, :zip, :ticket_subject, :ticket_description,
:ticket_problem_type, :ticket_id, :customer_id, :contact_id, :properties, :file_url

You can set "Custom Fields" using as hash/object/dict in the properties field. These will map over to the ticket custom fields when you convert it. Here is an example curl setting it via json:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d ' {"first_name":"John","last_name":"Smith","properties":{"device":"Apple"}}'

Customers /api/v1

  • index GET /customers
    Also supports search, pass a parameter named "query" to do a search
  • show GET /customers/:id
  • create POST /customers
  • update PUT /customers/:id
  • autocomplete GET /customers/autocomplete (with param query=STRING)
Valid parameters
:business_name, :firstname, :lastname, :email, :phone, :mobile, :address, :address_2, :city, :state, :zip, :notes, :get_sms, :opt_out, :no_email, :ref_customer_id, :referred_by, :properties, :disabled, :tax_rate_id, :notification_email, :invoice_cc_emails, :invoice_term_id
  • include_disabled
  • query
  • sort (looks like "id desc" or "updated_at desc")

Customers Phones Association /api/v1

  • index GET /customers/:id/phones
  • update PUT /customers/:id/phones/:phone_id
  • create POST /customers/:id/phones
Valid parameters
:label, :number, :extension

Contacts /api/v1

  • index GET /contacts.json?customer_id=123
  • show GET /contacts/123
  • create POST /contacts
  • update PUT /contacts/123
Valid Parameters
:customer_id, :name, :address1, :address2, :city, :state, :zip, :email,
                 :phone, :mobile, :notes

Example curl: 

curl --data "api_key=YOUR_API_KEY&customer_id=3411&name=Steve Jobs"

Invoices /api/v1

  • index GET /invoices
  • For GET we have some filters too: unpaid, paid, ticket_id, since_updated_at. You can pass a date into since_updated_at like "2017-01-01" or even a date+time "2017-01-01 14:00". unpaid/paid are just boolean
  • create POST /invoices

Valid parameters
:number, :date, :customer_id, :employee, :date_received,
:ticket_id, :took_payment, :paid, :location_id
:line_items [
 item, name, quantity, cost, price, taxable

Invoices Line Items /api/v1/invoices/:id/
 - create POST /invoices/:id/line_items
 - update PUT /invoices/:id/line_items/:line_item_id
 - delete DELETE /invoices/:id/line_items/:line_item_id

(Item and Name are known as item and description in the app)

Valid Params for Create: product_id, quantity, item, name, discount_dollars, line_discount_percent
Valid Params for Update: item, name - to change quantity or product, you must delete and create a new line item

Example curl to create an invoice with a line item:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d ' {"customer_id":"4972350","line_items":[{"item":"Test","product_id":"39","name":"Test","quantity":"2","cost":"10","price":"94.99","line_discount_percent":50}]}'

Example curl adding a discounted line item:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d ' {"product_id":"39","quantity":"2","line_discount_percent":50}'

Example curl updating the pricing on a line item:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X PUT -d ' {"cost":"10","price":"999.99"}' https://subdomain/api/v1/invoices/2792178/line_items/5286500?api_key=YOUR_API_KEY

Example curl creating a manual line item with pricing:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d ' {"item":"Test","name":"Test","quantity":"2","cost":"10","price":"94.99"}' http://subdomain/api/v1/invoices/2792178/line_items?api_key=YOUR_API_KEY

Payment Methods /api/v1

  • index GET /payment_methods
Read-Only - just to allow some integrations, our mobile app, etc

Tickets /api/v1

  • index GET /tickets (optional; customer_id, number, status=Not Closed, resolved_after=2017-01-10, since_updated_at=2017-01-01, term=subject_query_here, mine=true, ticket_search_id=123)
  • show GET /tickets/:id
  • new GET /tickets/new (instructions)
  • create POST /tickets
  • update PUT /tickets/:id
  • add comment POST /tickets/(:number or :id)/comment
  • add timer entry POST /tickets/:id/timer_entry - params: start_at, end_at OR duration_minutes, user_id(optional), notes(optional), product_id(optional), charge_time(true/false)(optional)
  • update timer entry PUT /tickets/:id/update_timer_entry with timer_entry_id and :notes,:start_time,:end_time
  • delete timer entry DELETE /tickets/:id/delete_timer_entry with timer_entry_id
  • attach file POST /tickets/:id/attach_file_url - params: needs an array named 'files' like : [{url: "", filename: 'optional-name.jpg}]
Valid parameters
ticket: :number, :subject, :created_at, :customer_id, :due_date,
:location_id, :problem_type, :status, :user_id, :asset_ids, :properties, :ticket_type_id

If you want to create the initial comment at the same time you can send the comment in a simpler way by using these attributes:

comment_body, comment_subject, comment_tech, comment_do_not_email, comment_hidden, comment_sms_body

Example curl 

curl --data "api_key=YOUR_API_KEY&customer_id=3411&subject=testing&problem_type=Virus&status=New&comment_body=just_testing&comment_subject=Initial Issue"


Body: The message body
Tech: a friendly name to show in the tech field
Do Not Email: boolean, send a "1" or "0" for if we should email the customer or not
Hidden: send a "1" or "0" for if this is a private comment
SMS Body: the body to get sent to customer via SMS

Sample CURL

curl --data "api_key=YOUR_API_KEY&customer_id=3411&subject=testing&problem_type=Virus&status=New&comment_subject=Update&comment_body=I am the body"

Ticket Charges api/v1

  • index GET tickets/:id (tons of detail is in the ticket detail endpoint here)
  • create POST tickets/:id/add_line_item
  • update PUT tickets/:id/update_line_item (ticket_line_item_id=)
  • delete DELETE tickets/:id/remove_line_item (ticket_line_item_id=:id)
Parameters: :name, :product_id, :description, :quantity, :price_cost, :price_retail, :taxable

Ticket Worksheets api/v1

  • coming soon

Ticket Attachments api/v1

  • create POST tickets/:id/attach_file_url
Parameters: :url - send a public URL to a file and we'll download it and attach it

Products /api/v1

  • index GET /products
    Also supports search, pass a param named "sku" to search for a SKU, or pass a param named "query" to do a text search
  • category filter /products?category_id=123
  • show GET /products/:id
  • new GET /products/new (instructions)
  • create POST /products
  • update PUT /products/:id
  • update LocationQuantity (big chain inventory levels) PUT /products/:id/location_quantities (needs location_quantity_id & quantity params)

Valid Parameters:

product: :price_cost, :price_retail, :condition, :description, :maintain_stock,
:name, :quantity, :warranty, :sort_order, :reorder_at, :disabled, :taxable,
:product_category, :upc_code, :discount_percent, :warranty_template_id, :qb_item_id,
:vendor_id, :desired_stock_level, :price_wholesale, :notes, :tax_rate_id,
:physical_location, :serialized

Product Photos 

You can now add photos to Products.
POST /api/v1/products/123/add_images
with params like: :url, :filename

You can also remove them:
DELETE /api/v1/products/123/delete_image?photo_id=123

Product Serials ("Instances") /api/v1/products/:123/product_serials

  • We added GET api/v1/products/:product_id/products_serials endpoint.
  • you can filter product serials by status: reserved, sold, returned, used_in_refurb, in_transfer, breakage, default is in_stock
  • We also added ability to update product serials via API PUT api/v1/products/:product_id/products_serials/:id endpoint.
  • supported params: condition, price_cost_cents, price_retail_cents, serial_number, notes
curl -X PUT '`product_id`/product_serials/`id`?api_key=`api_kley`&serial_number=NEW_SERIAL_NUMBER'
-curl -X GET '`product_id`/product_serials?api_key=`api_key`&status=in_stock'

Appointments /api/v1

  • index GET /appointments
    Optional param named "mine" will filter to the current user
  • show GET /appointments/:id
  • create POST /appointments
  • update PUT /appointments/:id
  • delete DELETE /appointments/:id
Index (list) parameters:
You can use these optional parameters: date_to, date_from, mine

Parameters for Appointments:
If you send an optional ticket_id, the appointment will attach to the ticket instead of just the account.

If you send just a start_at, and appointment_duration param - the appointment_duration looks like this: "6 hours"

You can also send a start_at and end_at, in typical computer formatting like: 2016-03-29 15:00 -0900

The "Owner" of the appointment is the user_id. Attendees are an array of user_ids.
:description, :user_ids, :do_not_email, :user_id,
:end_at, :location, :start_at, :summary, :email_customer,
:appointment_duration, :appointment_type, :appointment_type_id

Assets /api/v1

  • index GET /customer_assets
    customer_id - filters by a customer_id
    asset_type_id - filters by asset_type
    query - does a text search
  • show GET /customer_assets/:id
  • create POST /customer_assets
  • update PUT /customer_assets/:id

Valid parameters:
:name, :customer_id,
:asset_serial, :asset_type_id

Payments /api/v1

  • index GET /payments
  • show GET /payments/:id
  • create POST /payments
  • update PUT /payments/:id

Valid parameters
:invoice_id, :customer_id, :invoice_number, :amount_cents, :first_name, :last_name, :address_street, :address_city, :address_zip, :ref_num, :register_id, :payment_method, :signature_name, :signature_data

Employee Time Logs /api/v1

GET all timelogs for a user

curl -X GET ''

GET last timelog for user #2

curl -X GET ''

CREATE or UPDATE the last timelog(just as we do on web) available params are :lunch, :in_at, :out_at, :in_note, :out_note

in_at and out_at should be in the account's timezone

curl -X PUT ''

- the API key needs 'manage-timelogs' permission to edit other users' timelogs

Feedback and Knowledge Base