Service Fusion Invoices API
List, retrieve, and create invoices billed to customers for completed work, including line items, totals, balance due, and payment status. Includes an open-invoices view for outstanding accounts receivable.
List, retrieve, and create invoices billed to customers for completed work, including line items, totals, balance due, and payment status. Includes an open-invoices view for outstanding accounts receivable.
openapi: 3.0.3
info:
title: Service Fusion Open API
description: >-
The Service Fusion Open API is a REST/JSON interface to Service Fusion field
service management (FSM) software for home-service contractors. It exposes the
core operational records - customers and their contacts, jobs (work orders),
estimates, invoices, payments, the product/service catalog, technicians, and
calendar tasks - over HTTPS. Requests are authenticated with OAuth 2.0; obtain
an access token from the token endpoint at
https://api.servicefusion.com/oauth/access_token using an authorization_code
or client_credentials grant, then send it as a Bearer token. API access is
available on the Service Fusion Pro plan and is rate limited to roughly 60
requests per minute.
Grounding note - customers, jobs, estimates, invoices, and techs are
documented resources on the Service Fusion API. Contacts, products, services,
payments, and calendar tasks are modeled here from the Service Fusion FSM data
model and the platform's read-and-create API conventions; verify exact paths,
fields, and available methods against the live reference at
https://docs.servicefusion.com/ before production use. In practice the public
API is read-and-create heavy - list (GET), retrieve (GET), and create (POST)
are the reliably available operations; update (PUT) and delete (DELETE) are not
consistently exposed across resources.
version: '1.0'
contact:
name: Service Fusion
url: https://www.servicefusion.com
servers:
- url: https://api.servicefusion.com/v1
description: Service Fusion Open API v1
security:
- oauth2: []
- bearerAuth: []
tags:
- name: Customers
description: Customer accounts served by the contractor.
- name: Contacts
description: Individual contacts and service locations on a customer account.
- name: Jobs
description: Jobs (work orders) scheduled and dispatched to technicians.
- name: Estimates
description: Estimates (quotes) presented to customers before work begins.
- name: Invoices
description: Invoices billed to customers for completed work.
- name: Products and Services
description: Catalog of products (parts/inventory) and services (labor/tasks).
- name: Payments
description: Payments applied against invoices.
- name: Techs and Users
description: Technicians and users the work is assigned to.
- name: Calendar Tasks
description: Non-job scheduled calendar items and reminders.
paths:
/customers:
get:
operationId: listCustomers
tags: [Customers]
summary: List customers
description: Lists customer accounts. Supports filtering, sorting, field expansion, and pagination.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Expand'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of customers.
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerList'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimited'
post:
operationId: createCustomer
tags: [Customers]
summary: Create a customer
description: Creates a new customer account.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerInput'
responses:
'201':
description: The created customer.
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
'429':
$ref: '#/components/responses/RateLimited'
/customers/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getCustomer
tags: [Customers]
summary: Retrieve a customer
description: Retrieves a single customer account by ID.
parameters:
- $ref: '#/components/parameters/Expand'
responses:
'200':
description: The requested customer.
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/customers/{id}/contacts:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: listCustomerContacts
tags: [Contacts]
summary: List a customer's contacts
description: Lists the contacts and service locations attached to a customer account.
responses:
'200':
description: A list of contacts for the customer.
content:
application/json:
schema:
$ref: '#/components/schemas/ContactList'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
post:
operationId: createCustomerContact
tags: [Contacts]
summary: Add a contact to a customer
description: Creates a new contact under the given customer account.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContactInput'
responses:
'201':
description: The created contact.
content:
application/json:
schema:
$ref: '#/components/schemas/Contact'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/jobs:
get:
operationId: listJobs
tags: [Jobs]
summary: List jobs
description: >-
Lists jobs (work orders). Always pass a sort parameter (for example
sort=-start_date); unsorted /jobs list queries are known to hang.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Expand'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of jobs.
content:
application/json:
schema:
$ref: '#/components/schemas/JobList'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimited'
post:
operationId: createJob
tags: [Jobs]
summary: Create a job
description: Creates a new job (work order) for a customer.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/JobInput'
responses:
'201':
description: The created job.
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/jobs/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getJob
tags: [Jobs]
summary: Retrieve a job
description: Retrieves a single job by ID, with optional expanded relationships.
parameters:
- $ref: '#/components/parameters/Expand'
responses:
'200':
description: The requested job.
content:
application/json:
schema:
$ref: '#/components/schemas/Job'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/estimates:
get:
operationId: listEstimates
tags: [Estimates]
summary: List estimates
description: Lists estimates (quotes), with filtering, sorting, and pagination.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Expand'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of estimates.
content:
application/json:
schema:
$ref: '#/components/schemas/EstimateList'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createEstimate
tags: [Estimates]
summary: Create an estimate
description: Creates a new estimate for a customer with line items.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EstimateInput'
responses:
'201':
description: The created estimate.
content:
application/json:
schema:
$ref: '#/components/schemas/Estimate'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/estimates/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getEstimate
tags: [Estimates]
summary: Retrieve an estimate
description: Retrieves a single estimate by ID.
responses:
'200':
description: The requested estimate.
content:
application/json:
schema:
$ref: '#/components/schemas/Estimate'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/invoices:
get:
operationId: listInvoices
tags: [Invoices]
summary: List invoices
description: Lists invoices. Filter by status (e.g. open/unpaid) to view outstanding accounts receivable.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Expand'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of invoices.
content:
application/json:
schema:
$ref: '#/components/schemas/InvoiceList'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createInvoice
tags: [Invoices]
summary: Create an invoice
description: Creates a new invoice for a customer or completed job.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/InvoiceInput'
responses:
'201':
description: The created invoice.
content:
application/json:
schema:
$ref: '#/components/schemas/Invoice'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/invoices/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getInvoice
tags: [Invoices]
summary: Retrieve an invoice
description: Retrieves a single invoice by ID.
responses:
'200':
description: The requested invoice.
content:
application/json:
schema:
$ref: '#/components/schemas/Invoice'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/products:
get:
operationId: listProducts
tags: [Products and Services]
summary: List products
description: Lists catalog products (parts and inventory items).
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of products.
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogItemList'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createProduct
tags: [Products and Services]
summary: Create a product
description: Creates a new catalog product.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogItemInput'
responses:
'201':
description: The created product.
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogItem'
'401':
$ref: '#/components/responses/Unauthorized'
/services:
get:
operationId: listServices
tags: [Products and Services]
summary: List services
description: Lists catalog services (labor and flat-rate tasks).
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of services.
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogItemList'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createService
tags: [Products and Services]
summary: Create a service
description: Creates a new catalog service.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogItemInput'
responses:
'201':
description: The created service.
content:
application/json:
schema:
$ref: '#/components/schemas/CatalogItem'
'401':
$ref: '#/components/responses/Unauthorized'
/payments:
get:
operationId: listPayments
tags: [Payments]
summary: List payments
description: Lists payments recorded against invoices.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of payments.
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentList'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createPayment
tags: [Payments]
summary: Record a payment
description: Records a payment applied to an invoice.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentInput'
responses:
'201':
description: The recorded payment.
content:
application/json:
schema:
$ref: '#/components/schemas/Payment'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/techs:
get:
operationId: listTechs
tags: [Techs and Users]
summary: List techs and users
description: Lists the technicians and users in the account.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of techs and users.
content:
application/json:
schema:
$ref: '#/components/schemas/TechList'
'401':
$ref: '#/components/responses/Unauthorized'
/techs/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getTech
tags: [Techs and Users]
summary: Retrieve a tech
description: Retrieves a single technician or user by ID.
responses:
'200':
description: The requested tech or user.
content:
application/json:
schema:
$ref: '#/components/schemas/Tech'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/calendar-tasks:
get:
operationId: listCalendarTasks
tags: [Calendar Tasks]
summary: List calendar tasks
description: Lists non-job calendar tasks such as reminders and follow-ups.
parameters:
- $ref: '#/components/parameters/Filters'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/PerPage'
responses:
'200':
description: A paginated list of calendar tasks.
content:
application/json:
schema:
$ref: '#/components/schemas/CalendarTaskList'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createCalendarTask
tags: [Calendar Tasks]
summary: Create a calendar task
description: Creates a new calendar task, optionally assigned to a tech or user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CalendarTaskInput'
responses:
'201':
description: The created calendar task.
content:
application/json:
schema:
$ref: '#/components/schemas/CalendarTask'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
components:
securitySchemes:
oauth2:
type: oauth2
description: OAuth 2.0. Access tokens are issued at https://api.servicefusion.com/oauth/access_token.
flows:
authorizationCode:
authorizationUrl: https://api.servicefusion.com/oauth/authorize
tokenUrl: https://api.servicefusion.com/oauth/access_token
scopes: {}
clientCredentials:
tokenUrl: https://api.servicefusion.com/oauth/access_token
scopes: {}
bearerAuth:
type: http
scheme: bearer
description: Bearer access token obtained via the OAuth 2.0 token endpoint.
parameters:
Id:
name: id
in: path
required: true
description: The unique identifier of the resource.
schema:
type: string
Filters:
name: filters
in: query
required: false
description: >-
Field filters, expressed as filters[field]=value (for example
filters[status]=open). Repeat for multiple fields.
style: deepObject
explode: true
schema:
type: object
additionalProperties:
type: string
Sort:
name: sort
in: query
required: false
description: >-
Sort field, optionally prefixed with - for descending order (for example
sort=-start_date). Required on /jobs list requests.
schema:
type: string
Expand:
name: expand
in: query
required: false
description: Comma-separated list of related resources to inline in the response.
schema:
type: string
Page:
name: page
in: query
required: false
description: 1-based page number for pagination.
schema:
type: integer
minimum: 1
default: 1
PerPage:
name: per-page
in: query
required: false
description: Number of records per page.
schema:
type: integer
minimum: 1
maximum: 100
default: 25
responses:
Unauthorized:
description: Missing or invalid OAuth 2.0 access token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: The requested resource was not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ValidationError:
description: The request body failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
RateLimited:
description: Rate limit exceeded (roughly 60 requests per minute). Honor Retry-After and back off.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Pagination:
type: object
properties:
current_page:
type: integer
per_page:
type: integer
total:
type: integer
Error:
type: object
properties:
error:
type: string
message:
type: string
Address:
type: object
properties:
street_1:
type: string
street_2:
type: string
city:
type: string
state_prov:
type: string
postal_code:
type: string
country:
type: string
Customer:
type: object
properties:
id:
type: string
customer_name:
type: string
account_number:
type: string
phones:
type: array
items:
type: object
properties:
phone:
type: string
type:
type: string
emails:
type: array
items:
type: string
address:
$ref: '#/components/schemas/Address'
created_at:
type: string
format: date-time
CustomerInput:
type: object
required: [customer_name]
properties:
customer_name:
type: string
phones:
type: array
items:
type: object
properties:
phone:
type: string
type:
type: string
emails:
type: array
items:
type: string
address:
$ref: '#/components/schemas/Address'
CustomerList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Customer'
_meta:
$ref: '#/components/schemas/Pagination'
Contact:
type: object
properties:
id:
type: string
customer_id:
type: string
fname:
type: string
lname:
type: string
contact_type:
type: string
phone:
type: string
email:
type: string
address:
$ref: '#/components/schemas/Address'
ContactInput:
type: object
required: [fname]
properties:
fname:
type: string
lname:
type: string
contact_type:
type: string
phone:
type: string
email:
type: string
address:
$ref: '#/components/schemas/Address'
ContactList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Contact'
_meta:
$ref: '#/components/schemas/Pagination'
Job:
type: object
properties:
id:
type: string
number:
type: string
customer_name:
type: string
description:
type: string
status:
type: string
category:
type: string
start_date:
type: string
format: date-time
end_date:
type: string
format: date-time
techs:
type: array
items:
type: string
total:
type: number
JobInput:
type: object
required: [customer_name]
properties:
customer_name:
type: string
description:
type: string
category:
type: string
status:
type: string
start_date:
type: string
format: date-time
end_date:
type: string
format: date-time
techs:
type: array
items:
type: string
JobList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Job'
_meta:
$ref: '#/components/schemas/Pagination'
LineItem:
type: object
properties:
name:
type: string
description:
type: string
quantity:
type: number
unit_price:
type: number
taxable:
type: boolean
Estimate:
type: object
properties:
id:
type: string
number:
type: string
customer_name:
type: string
status:
type: string
total:
type: number
line_items:
type: array
items:
$ref: '#/components/schemas/LineItem'
created_at:
type: string
format: date-time
EstimateInput:
type: object
required: [customer_name]
properties:
customer_name:
type: string
line_items:
type: array
items:
$ref: '#/components/schemas/LineItem'
EstimateList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Estimate'
_meta:
$ref: '#/components/schemas/Pagination'
Invoice:
type: object
properties:
id:
type: string
number:
type: string
customer_name:
type: string
status:
type: string
total:
type: number
balance_due:
type: number
line_items:
type: array
items:
$ref: '#/components/schemas/LineItem'
created_at:
type: string
format: date-time
InvoiceInput:
type: object
required: [customer_name]
properties:
customer_name:
type: string
job_id:
type: string
line_items:
type: array
items:
$ref: '#/components/schemas/LineItem'
InvoiceList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Invoice'
_meta:
$ref: '#/components/schemas/Pagination'
CatalogItem:
type: object
properties:
id:
type: string
name:
type: string
description:
type: string
price:
type: number
cost:
type: number
taxable:
type: boolean
CatalogItemInput:
type: object
required: [name]
properties:
name:
type: string
description:
type: string
price:
type: number
cost:
type: number
taxable:
type: boolean
CatalogItemList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/CatalogItem'
_meta:
$ref: '#/components/schemas/Pagination'
Payment:
type: object
properties:
id:
type: string
invoice_id:
type: string
amount:
type: number
method:
type: string
date:
type: string
format: date
PaymentInput:
type: object
required: [invoice_id, amount]
properties:
invoice_id:
type: string
amount:
type: number
method:
type: string
date:
type: string
format: date
PaymentList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Payment'
_meta:
$ref: '#/components/schemas/Pagination'
Tech:
type: object
properties:
id:
type: string
fname:
type: string
lname:
type: string
email:
type: string
phone:
type: string
role:
type: string
TechList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Tech'
_meta:
$ref: '#/components/schemas/Pagination'
CalendarTask:
type: object
properties:
id:
type: string
title:
type: string
description:
type: string
start_date:
type: string
format: date-time
end_date:
type: string
format: date-time
assigned_to:
type: string
CalendarTaskInput:
type: object
required: [title]
properties:
title:
type: string
description:
type: string
start_date:
type: string
format: date-time
end_date:
type: string
format: date-time
assigned_to:
type: string
CalendarTaskList:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/CalendarTask'
_meta:
$ref: '#/components/schemas/Pagination'