API Guide

The Minute7 API lets you pull your account's time and expense data as reports, and bulk-load reference data into your account from CSV. It is a JSON HTTP API for Minute7 customers building integrations against their own data.

Every request is authenticated and scoped to a single Minute7 account: it only ever accesses data belonging to that account, never another. The reporting endpoints return JSON and can also stream CSV, XLSX, and PDF downloads; the import endpoints accept CSV uploads. If you are just getting started, read Authentication and Conventions first, then use the contents below to jump to the section you need.

Contents

Authentication

There are two separate authentication mechanisms. The reporting endpoints use a per-user login token (described first). The bulk data-import endpoints use a separate account token (described last). They are not interchangeable.

Login token (used by the reporting endpoints)

The reporting endpoints authenticate with a per-user login token (a JWT). You obtain it by logging in, or a user with API access can copy it from My Settings in the Minute7 web app (it appears there as the user's TOKEN).

Obtaining the token

Send a POST to the login endpoint with the credentials nested under a user key:

POST https://www.minute7.com/api/login
Content-Type: application/json

{ "user": { "email": "you@example.com", "password": "your-password" } }

On success the response contains a logininfo object. The token is the value at logininfo.session.session_id (the companion logininfo.session.session_name is the literal string IMPRESARIO). The same JWT is also returned in the Authorization response header. The logininfo object also carries AccountUser and Account siblings alongside session — read the token specifically from logininfo.session.session_id, not from the body as a whole. A success response looks like:

{"logininfo":{"session":{"session_name":"IMPRESARIO","session_id":"<jwt>"},"AccountUser":{...},"Account":{...}}}

On invalid credentials the response is {"errors":[{"session":"Invalid credentials"}]} with HTTP 401; a locked account returns {"errors":[{"session":"User account locked"}]} with HTTP 403. Login is rate limited per IP address (up to 10 attempts per IP per 10 minutes); exceeding it returns HTTP 429 (see Conventions > Rate limiting).

Presenting the token

There are two accepted ways to present the token; both are accepted interchangeably (the IMPRESARIO parameter is rewritten into the Authorization header before the request is authenticated).

The IMPRESARIO parameter exists for clients (such as the Minute7 web front-end) that cannot easily set request headers, and is fully supported. As a best practice, prefer the Authorization: Bearer header where you can — it keeps the token out of URLs, query strings, and browser history.

Example read call using the header:

curl -H 'Authorization: Bearer <token>' \
  'https://www.minute7.com/api/reports/time_json?report_customer_id=&report_employee_id=&report_qb_class_id=&report_inventory_item_id=&report_payroll_item_id='

The same call using the parameter form:

https://www.minute7.com/api/reports/time_json?IMPRESARIO=<token>&report_customer_id=&report_employee_id=&report_qb_class_id=&report_inventory_item_id=&report_payroll_item_id=

Account token (used only by the Data Import endpoints)

The bulk CSV import and ID-map endpoints (see "Data Import" below) use a separate, account-scoped token. There is no self-service screen for this token — Minute7 issues it for your account on request, so contact support to obtain one. Once you have it, send it in the Authorization header in either of these forms:

Authorization: Bearer <your-token>
Authorization: Token token=<your-token>

Both are accepted and behave identically; the Bearer form is the simpler of the two. This token is separate from the login token, and the IMPRESARIO query parameter is not accepted here.

Each token belongs to exactly one account; everything imported under it is attributed to that account. Tokens are named and can be deactivated, and only active tokens authenticate. Tokens are stored hashed — the raw value is shown once when the token is created, so treat it like a password.

Permissions and visibility

Holding a valid token is not always sufficient — the calling user must also be permitted to use the API. Account administrators have API access by default; other users are granted it under their permission settings.

The report endpoints in particular require that the user either manages the account or has the "communicate with API" permission enabled, and report results are limited to the employees that user is allowed to see. An administrator configures this per user: allow the user to view reports, choose which employees they may view, and allow them to communicate with the API.

Conventions

Time Reports

Time report (JSON)

GET https://www.minute7.com/api/reports/time_json

Returns the account's time entries as JSON, filtered by date range and any of several optional filters. Requires account-management rights or the "communicate with API" permission; results are limited to the employees the calling user may view.

Note: the report_* filter parameters must be present on the request (they may be sent empty). Sending an empty value applies no filter for that dimension; omitting the parameter entirely results in a 400.

Parameters

Response

Optional attributes (opt-in via include)

Time report (CSV / XLSX / PDF export)

GET https://www.minute7.com/api/reports/time_csv , https://www.minute7.com/api/reports/time_xlsx , https://www.minute7.com/api/reports/time_pdf

Streams the same filtered time entries as a file download. The CSV and XLSX exports take an export_time_fields parameter that chooses and orders the columns; the PDF export does not. The downloaded file is named after your account (e.g. <account name>_time_export.csv). These exports require only authentication; they accept the same date and report_* filter parameters as the JSON report.

Parameters

Response

Time segments (aggregate totals)

POST https://www.minute7.com/api/reports/segment_time

Aggregates the filtered time entries into a nested tree of duration sums, grouped by one or more dimensions.

Parameters

Response

Expense Reports

Expense report (JSON)

GET https://www.minute7.com/api/reports/expenses

Returns the account's expense entries as JSON, filtered by date range and optional filters. Requires account-management rights or the "communicate with API" permission. As with the time report, the report_* filter parameters must be present (they may be empty).

Parameters

Response

Expense report (CSV / XLSX / PDF export)

GET https://www.minute7.com/api/reports/expenses_csv , https://www.minute7.com/api/reports/expenses_xlsx , https://www.minute7.com/api/reports/expenses_pdf

Streams the same filtered expense entries as a file download. CSV and XLSX take an export_expense_fields parameter selecting the columns; PDF does not. The file is named after your account (e.g. <account name>_expenses_export.csv). The same date and filter parameters as the expense JSON report apply.

Parameters

Response

Expense attachments (ZIP download)

GET https://www.minute7.com/api/reports/download_expense_attachments

Bundles the receipt/attachment files of the filtered expense entries into a single ZIP and streams it as a download (filename <account name>_attachment_export.zip). Accepts the same date and filter parameters as the expense report.

Response

Expense segments (aggregate totals)

POST https://www.minute7.com/api/reports/segment_expenses

Aggregates the filtered expense entries into a nested tree of amount sums, grouped by one or more dimensions.

Parameters

Response

Data Import

The import endpoints bulk-load your reference data (customers, vendors, employees, items, payroll items, QuickBooks accounts and classes) into your account from CSV. The ID-map endpoint remaps the external ids stored on your records — useful when you move your data to a different accounting system. All of these use the account token described under Authentication — Authorization: Bearer <your-token> — not the login token. The column names below follow Minute7's QuickBooks-based field naming; map your source data into the columns shown for each list type.

How imports work

Request format

Send the CSV one of two ways: as a multipart form upload in a file field, or as the raw CSV in the request body with Content-Type: text/csv. The first row must be a header row; column order does not matter.

You may include any subset of an importer's columns — missing columns are simply not set. Any column whose name is not one of the importer's recognized headers causes the whole request to be rejected (see Response). Each import also accepts an optional inactivate_missing form/query parameter (default false) — see "Removing records" below.

Common columns (accepted by every import)

How rows are applied

Each row is an upsert keyed on list_id, scoped to the token's account: existing records are updated in place, new list_id values are created. Records are never deleted by an import.

Removing records

Pass inactivate_missing=true to treat the upload as the full set: after applying the rows, any currently-active record of that type in your account whose list_id is not present in the file is marked inactive (hidden). With the default false, records absent from the file are left untouched.

Processing and errors

Imports run asynchronously. A well-formed request returns 202 Accepted immediately and the rows are applied by a background job; there is no status endpoint to poll. This means only request-level problems are reported in the response (a missing or malformed CSV, or an unrecognized column — all 400). Problems with individual rows during processing are recorded on the server, not returned to you. Confirm the result by reading it back through the reports or in the Minute7 web app.

Import order

Some records reference others by list_id, so import the referenced records first. In particular, import payroll items before employees (an employee row's payroll_item_list_ids are resolved against payroll items already in your account).

Example

A minimal customers upload (raw text/csv body):

list_id,is_active,full_name,bill_address_city,bill_address_state
80000001-1A2B3C4D,Y,Acme Corporation,Portland,OR

Import endpoints

Each endpoint below accepts the two common columns above plus the entity-specific columns listed with it.

Accounts

POST https://www.minute7.com/api/v1/import/accounts — your QuickBooks chart of accounts. full_name is used as the name when present, otherwise name.

Classes

POST https://www.minute7.com/api/v1/import/classes — your QuickBooks classes.

Customers

POST https://www.minute7.com/api/v1/import/customers — customers. full_name populates both the customer name and company name.

Employees

POST https://www.minute7.com/api/v1/import/employees — employees. print_as becomes the employee's display name. payroll_item_list_ids is a comma-separated list of payroll-item list_ids and is resolved against payroll items already imported into your account.

Inventory items

POST https://www.minute7.com/api/v1/import/inventory-items — inventory items.

Payroll items

POST https://www.minute7.com/api/v1/import/payroll-items — payroll items. wage_type accepts one of: None, Bonus, Commission, HourlyOvertime, HourlyRegular, HourlySick, HourlyVacation, SalaryRegular, SalarySick, SalaryVacation, RegularPay, OverTimePay, LeavePay.

Service items

POST https://www.minute7.com/api/v1/import/service-items — service items.

Vendors

POST https://www.minute7.com/api/v1/import/vendors — vendors. name_on_check sets the print-as name; is_vendor_eligible_for1099 = Y flags the vendor as 1099-eligible.

Response (all import endpoints)

ID map

POST https://www.minute7.com/api/v1/idmap

Updates the external id stored on existing records (their list_id) when the system those ids come from changes. It is intended for accounts that have moved off QuickBooks to another accounting system that Minute7 does not sync with directly, and need their Minute7 records to carry the new system's identifiers — for example, after switching from QuickBooks to Sage 100, remapping each record from its old QuickBooks id to its new id.

For each row it finds the record of the given type in your account whose current list_id equals old_id, and changes that record's list_id to new_id. Supply the CSV as a multipart file upload or a raw text/csv body.

Columns (all required)

Rows with any blank field are skipped.

Example

type,old_id,new_id
customers,80000001-OLD,80000045-NEW
vendors,80000010-OLD,80000099-NEW

Response

The remapping runs in the background, so as with imports, a row whose old_id matches no record is recorded server-side and not returned in the response.

QuickBooks Synchronization

Minute7 synchronizes time and expense data with QuickBooks Online and QuickBooks Desktop. This synchronization is handled within the Minute7 application itself and is not part of the integration API described here; there are no integration endpoints for driving or configuring it.