Overview
The Standard Time® Zapier integration exposes a REST API that the Zapier platform uses to build automated workflows between Standard Time® and thousands of other apps. The integration is bidirectional:
- Triggers — Standard Time® fires a webhook to Zapier whenever a record is created or updated (projects, tasks, time logs, expenses, users, clients, subprojects, inventory items, categories, invoices, and billing rates).
- Actions — Zapier calls Standard Time® endpoints to create or update records in response to events in other apps.
The API consists of 30 endpoints in total, grouped into five categories: authentication, webhook subscription management, sample data, dynamic dropdowns, and actions.
| Category | Endpoints | Purpose |
|---|---|---|
| Authentication | 1 | Validate API key credentials and return user identity |
| REST Hooks | 2 | Subscribe and unsubscribe Zapier webhook URLs |
| Sample Data | 1 | Return a sample record for Zapier trigger setup |
| Dynamic Dropdowns | 6 | Populate project, user, client, subproject, category, and inventory pickers in Zapier's UI |
| Actions | 20 | Create and update projects, tasks, time logs, expenses, clients, subprojects, inventory items, categories, invoices, and billing rates |
| Total | 30 |
Every record type above also has a matching pair of New / Updated REST Hook triggers — 11 record types × 2 events = 22 triggers in total. Users are read-only from Zapier's perspective: there's a New User / Updated User trigger and a GetUsers dropdown endpoint, but no create/update action, since user accounts are provisioned inside Standard Time® directly.
What's New in Version 2.0.0
Version 2.0.0 adds six new record types to the integration — Client, Subproject, Inventory, Category, Invoice, and Billing Rate — each with a full set of create/update actions, New/Updated triggers, and (where applicable) a dynamic dropdown endpoint. It also renames the Time Entry entity to Time Log and fixes several long-standing field-mapping bugs.
trigger/timeentry_createdandtrigger/timeentry_updatedare replaced bytrigger/timelog_createdandtrigger/timelog_updated, matching the "time log" terminology used elsewhere in Standard Time®.create/timeentry_createdandcreate/timeentry_updatedare replaced bycreate/create_timelogandcreate/update_timelog.- Update Project's
Descriptionfield is now multi-line text instead of a single-line string. - Create/Update Expense's
TypeIdfield has been removed; useCategoryIdinstead.
- Create/Update Client — most fields (address, city, state, zip, country, phone, fax, website, payment terms, etc.) were being silently dropped due to a field-name mismatch and never reached the database. All fields now persist correctly.
- Create/Update Invoice — the
Amount,TaxRate, andInvoiceNotefields were silently dropped and never saved. All three now persist correctly. - Create/Update Billing Rate — the
RateTypefield is now a proper numeric value instead of a string. - Boolean fields (
Billable,Reimbursable,Active,Approved,Completed, and others) across every trigger and create/update action now return realtrue/falsevalues instead of text. - Numeric fields (
ClientRate,SalaryRate,Qty, cost fields, and others) across the same set of triggers and actions now return real numbers instead of text. - Authentication — the connected Zapier account is now labeled by Site URL, making it easier to tell multiple connections apart when a user connects more than one Standard Time® site.
Authentication
Every request to the Standard Time® Zapier API must include two HTTP headers identifying the account and proving ownership of a valid API key.
| Header | Value | Example |
|---|---|---|
X-ST-Customer-Id |
Your Standard Time® customer/account identifier | cust_abc123 |
X-ST-Api-Key |
Your Standard Time® API key (generated in-app) | st_Abc1234… |
The customer's Site URL (e.g. https://mycompany.standardtime.com) is also collected during the "Connect Account" step and stored alongside the credentials. Since v2.0.0, each connected account is labeled by its Site URL rather than a generic name, making it easy to tell multiple Standard Time® connections apart.
API Key Format
Keys are prefixed with st_ followed by 32 random bytes encoded as URL-safe Base64. Example prefix shown in the app: st_Abc1234 (truncated for display). The full key is shown only once at generation time — Standard Time® stores only a SHA-256 hash and will never display the plaintext key again.
Fallback Authentication
If the two custom headers are absent, the authentication filter also accepts:
Authorization: Bearer {apiKey}HTTP header?apiKey={apiKey}query string parameter (last resort)
The custom headers are the recommended and required form for the Zapier integration.
Auth Failures
Invalid or missing credentials return HTTP 401 Unauthorized with an empty body. All other errors return HTTP 200 with a JSON body containing "Success": false and an error message.
Base URL & Routes
All endpoints share the following base path pattern:
{{bundle.authData.siteUrl}}/zapier/{action}
{{bundle.authData.siteUrl}}/zapier/{action}/{id}
The siteUrl is the URL of the customer's Standard Time® web installation — for example, https://mycompany.standardtime.com. It is collected once during Zapier authentication and stored in bundle.authData.siteUrl.
The route segment {action} is the endpoint name (e.g., TestAuth, CreateProject). The optional {id} segment carries a record GUID where required (e.g., the Unsubscribe endpoint).
Response Format
All successful action and query responses return JSON with the following envelope:
{
"Success": true,
"Data": { ... },
"ErrorResults": ""
}
Error responses (application-level) use the same envelope with Success: false:
{
"Success": false,
"Data": null,
"ErrorResults": "Human-readable error description"
}
All datetimes are ISO 8601 UTC strings (2025-06-01T14:30:00Z). All record identifiers are GUIDs in lowercase hyphenated format (d290f1ee-6c54-4b01-90e6-d701748f0851).
TestAuth returns its identifying fields (Id, Username, Email) as flat top-level properties rather than nested under Data, and Sample returns a raw JSON array with no envelope at all. See the Auth Test Endpoint and Sample Data Endpoint sections below for exact shapes.
Auth Test Endpoint
Used by Zapier during the "Connect Account" step to verify that the provided credentials are valid and return identifying information about the authenticated user.
Request: No body. Authentication headers only.
Response:
{
"Success": true,
"Id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"Username": "jsmith",
"Email": "jsmith@example.com",
"ErrorResults": ""
}
Zapier displays the Username and Email fields to the user as confirmation that the correct account was connected. Note that these fields are flat top-level properties rather than nested under a Data object, unlike every other endpoint on this page.
REST Hook Endpoints
Standard Time® uses Zapier's REST Hook pattern for triggers. When a user activates a Zap, Zapier calls the Subscribe endpoint to register a callback URL. When the Zap is turned off or deleted, Zapier calls the Unsubscribe endpoint to deregister it.
Subscribe
Request body:
{
"hookUrl": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
"EventType": "project.created"
}
| Field | Type | Description | |
|---|---|---|---|
| hookUrl | string | required | The Zapier webhook URL to POST events to |
| EventType | string | required | One of the 22 event type keys listed in the Trigger Reference |
Response:
{
"Success": true,
"Id": "a3f2c1b0-d4e5-4f67-8901-23456789abcd",
"ErrorResults": ""
}
The Id is the subscription GUID. Zapier stores this and sends it back when unsubscribing.
Unsubscribe
{id} is the subscription GUID returned by Subscribe. No request body is required.
Response:
{ "Success": true, "ErrorResults": "" }
Sample Data Endpoint
Zapier calls this endpoint during trigger setup to show the user a sample record. This allows Zapier users to map fields from a Standard Time® event to fields in downstream apps without waiting for a real event to fire.
{eventType} is a URL-encoded event type string, such as project.created.
Response: A raw JSON array containing a single sample record matching the schema of the event type — there is no Success/Data/ErrorResults envelope on this endpoint. See the Webhook Payload Schemas section for field lists per event type.
[
{
"id": "00000000-0000-0000-0000-000000000001",
"name": "Sample Project",
"description": "A sample project record",
"clientId": "",
"status": "Active",
"priority": "",
"active": true,
"projectCode": "",
"startDate": "2025-01-06",
"finishDate": "2025-03-28",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
]
Sample records are static, hand-written fixtures — one per event type (22 total) — and are not read from the live database.
Dynamic Dropdown Endpoints
These endpoints power the project, user, client, subproject, category, and inventory pickers inside Zapier's action configuration UI, allowing users to select records by name rather than typing raw GUIDs. All six follow the same { "Success": true, "Data": [...], "ErrorResults": "" } envelope.
Get Projects
Returns all projects accessible to the authenticated user.
{
"Success": true,
"Data": [
{ "id": "d290f1ee-6c54-4b01-90e6-d701748f0851", "name": "Website Redesign" },
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Factory Line 3 Audit" }
],
"ErrorResults": ""
}
Get Users
Returns all users in the account.
{
"Success": true,
"Data": [
{ "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "username": "jsmith", "name": "Jane Smith" },
{ "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "username": "mwilson", "name": "Mike Wilson" }
],
"ErrorResults": ""
}
Get Clients New in 2.0.0
Returns all clients in the account. Powers the ClientId dynamic dropdown used by Project, Expense, Client (update), Subproject, and Invoice actions.
{
"Success": true,
"Data": [
{ "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "companyName": "Acme Corporation" }
],
"ErrorResults": ""
}
Get Subprojects New in 2.0.0
Returns all subprojects in the account. Powers the SubprojectId dynamic dropdown used by Task, Time Log, Expense, Invoice, and Category actions.
{
"Success": true,
"Data": [
{ "id": "a3bb189e-8bf9-3888-9912-ace4e6543002", "name": "Phase 1" }
],
"ErrorResults": ""
}
Get Categories New in 2.0.0
Returns all categories in the account. Powers the CategoryId dynamic dropdown used by Task, Time Log, Expense, and Billing Rate actions.
{
"Success": true,
"Data": [
{ "id": "9b2d3f1a-4e8c-4a7b-b92d-3f5e2a1c8d4e", "name": "Development" }
],
"ErrorResults": ""
}
Get Inventory New in 2.0.0
Returns all inventory items in the account.
{
"Success": true,
"Data": [
{ "id": "c56a4180-65aa-42ec-a945-5fd21dec0538", "name": "Laptop" }
],
"ErrorResults": ""
}
Action Endpoints
Action endpoints let Zapier create or update records in Standard Time® in response to events in other apps. All action endpoints use POST. Update endpoints apply only the fields present and non-empty in the request body — omitted or blank fields are left unchanged. Required/optional below reflects what the server itself enforces; the Zapier UI may additionally require a field at compose time even when the server accepts it blank (noted where relevant).
Projects
Create Project
| Field | Type | Description | |
|---|---|---|---|
| Name | string | required | Project name |
| Description | text | optional | Project description — multi-line text as of v2.0.0 |
| ClientId | GUID | optional | Client record identifier (dynamic dropdown) |
| Status | string | optional | e.g., Active, Inactive, Complete |
| Priority | string | optional | Priority label |
| BillingType | string | optional | Numeric billing type code as text; safe default is "1" (by user) |
| PO | string | optional | Purchase order reference (text only) |
| StartDate | date | optional | ISO 8601 date, e.g., 2025-01-06 |
| FinishDate | date | optional | ISO 8601 date |
| LaunchDate | date | optional | ISO 8601 date |
| DeliveryDate | date | optional | ISO 8601 date |
| QuotedDuration | string | optional | Quoted duration estimate |
| QuotedCost | string | optional | Quoted cost estimate |
| UserText1 / UserText2 / UserText3 | string | optional | Custom user-defined text fields |
Update Project
Same fields as Create Project, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the project to update |
| All Create Project fields | optional | Any subset of fields to update; non-empty values only are applied |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"name": "Website Redesign",
"description": "Q1 redesign project",
"clientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "Active",
"priority": "",
"active": true,
"projectCode": "",
"billingType": "",
"clientRate": 0.00,
"salaryRate": 0.00,
"qty": 0.00,
"qtyBuilt": 0.00,
"startDate": "2025-01-06",
"finishDate": "2025-03-28",
"launchDate": "",
"deliveryDate": "",
"quotedDuration": "",
"quotedCost": "",
"po": "",
"userText1": "",
"userText2": "",
"userText3": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
},
"ErrorResults": ""
}
Tasks
Create Task
| Field | Type | Description | |
|---|---|---|---|
| Name | string | required | Task name |
| ProjectId | GUID | required | Parent project identifier |
| SubprojectId | GUID | optional | Subproject identifier (dynamic dropdown) |
| CategoryId | GUID | optional | Category identifier (dynamic dropdown) |
| Description | string | optional | Task description |
| Status | string | optional | e.g., Active, Complete |
| Priority | string | optional | Priority label |
| StartDate | date | optional | ISO 8601 date |
| FinishDate | date | optional | ISO 8601 date |
| DueDate | date | optional | ISO 8601 date |
| PercentComplete | integer | optional | 0–100 |
| AssignedUserIds | string | optional | Comma-separated list of user GUIDs to assign |
| Billable | boolean | optional | Whether time logged against this task is billable |
| QuotedCost | string | optional | Quoted cost estimate |
| UserText1 / UserText2 / UserText3 | string | optional | Custom user-defined text fields |
Update Task
Same fields as Create Task, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the task to update |
| All Create Task fields | optional | Any subset; PercentComplete is applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "Design Mockups",
"description": "Initial wireframes",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"subprojectId": "",
"categoryId": "",
"clientId": "",
"status": "Active",
"priority": "",
"percentComplete": 0,
"completed": false,
"billable": true,
"startDate": "2025-01-07",
"finishDate": "2025-01-21",
"dueDate": "",
"completedDate": "",
"durationHours": 0.00,
"actualHours": 0.00,
"remainingHours": 0.00,
"costClient": 0.00,
"costSalary": 0.00,
"costClientActual": 0.00,
"costClientRemain": 0.00,
"costSalaryActual": 0.00,
"costSalaryRemain": 0.00,
"clientRate": 0.00,
"salaryRate": 0.00,
"quotedCost": "",
"qty": 0.00,
"qtyBuilt": 0.00,
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-07T09:00:00Z",
"modified": "2025-01-07T09:00:00Z"
},
"ErrorResults": ""
}
Time Logs renamed from Time Entry in 2.0.0
Create Time Log
| Field | Type | Description | |
|---|---|---|---|
| ProjectId | GUID | required | Project this time log is logged against |
| ProjectTaskId | GUID | optional | Task within the project |
| SubprojectId | GUID | optional | Subproject identifier (dynamic dropdown) |
| CategoryId | GUID | optional | Category identifier (dynamic dropdown) |
| UserId | GUID | optional | User who logged the time; defaults to the authenticated user |
| StartTime | datetime | optional | ISO 8601 UTC datetime |
| EndTime | datetime | optional | ISO 8601 UTC datetime |
| DurationHours | number | optional | Duration in hours (used when StartTime/EndTime are not provided). Stored as seconds in the DB — divide/multiply by 3600 is handled automatically. |
| Description | text | optional | Work notes or memo |
| Billable | boolean | optional | Whether this time is billable |
Update Time Log
Same fields as Create Time Log, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the time log to update |
| All Create Time Log fields | optional | Any subset; DurationHours is applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "e5f6a7b8-c9d0-1234-efab-234567890123",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"taskId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"subprojectId": "",
"categoryId": "",
"userId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"clientId": "",
"startTime": "2025-01-08T13:00:00Z",
"date": "2025-01-08",
"endTime": "2025-01-08T15:30:00Z",
"durationHours": 2.5,
"description": "Completed wireframe review",
"billable": true,
"billed": false,
"approved": false,
"costClient": 0.00,
"costSalary": 0.00,
"clientRate": 0.00,
"salaryRate": 0.00,
"qty": 0.00,
"location": "",
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-08T15:30:00Z",
"modified": "2025-01-08T15:30:00Z"
},
"ErrorResults": ""
}
Expenses
Create Expense
| Field | Type | Description | |
|---|---|---|---|
| ProjectId | GUID | required | Project this expense is charged to |
| ClientId | GUID | optional | Client identifier (dynamic dropdown) |
| SubprojectId | GUID | optional | Subproject identifier (dynamic dropdown) |
| CategoryId | GUID | optional | Category identifier (dynamic dropdown). Replaces the removed TypeId field. |
| UserId | GUID | optional | User submitting the expense; defaults to the authenticated user |
| Amount | number | optional | Expense amount in account currency |
| Price | number | optional | Unit price |
| Qty | number | optional | Quantity |
| Tax | number | optional | Tax amount |
| StartDate | date | optional | ISO 8601 date the expense was incurred |
| Description | text | optional | Memo or receipt description |
| PO | string | optional | Purchase order reference (text only) |
| Location | string | optional | Free-text location |
| Billable | boolean | optional | Whether this expense is billable to the client |
| Reimbursable | boolean | optional | Whether this expense is reimbursable to the user |
| UserText1 / UserText2 / UserText3 | string | optional | Custom user-defined text fields |
UserId, Amount, and Description as required at compose time, even though the server itself only rejects a request that's missing ProjectId.
Update Expense
Same fields as Create Expense, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the expense to update |
| All Create Expense fields | optional | Any subset; Amount, Price, Qty, and Tax are applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "f6a7b8c9-d0e1-2345-fabc-345678901234",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"clientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"subprojectId": "",
"categoryId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"userId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"expenseDate": "2025-01-09",
"amount": 124.50,
"price": 0.00,
"qty": 0.00,
"tax": 0.00,
"mileageRate": 0.00,
"distance": 0.00,
"odometerBegin": 0.00,
"odometerEnd": 0.00,
"description": "Conference travel",
"po": "",
"payee": "",
"checkNum": "",
"location": "",
"billable": true,
"billed": false,
"reimbursable": false,
"reimbursed": false,
"companyPaid": false,
"approved": false,
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-09T10:00:00Z",
"modified": "2025-01-09T10:00:00Z"
},
"ErrorResults": ""
}
Clients New in 2.0.0
Create Client
| Field | Type | Description | |
|---|---|---|---|
| CompanyName | string | required | Client company name |
| Description | text | optional | Client description |
| Status | string | optional | e.g., Active, Inactive |
| Priority | string | optional | Priority label |
| Terms | string | optional | Payment terms, e.g. Net 30 |
| Web | string | optional | Website URL |
| MainContact / MainContactPhone / MainContactMobile / MainContactFax / MainContactEmail | string | optional | Primary contact details |
| MainAddress1 / MainAddress2 / MainCity / MainState / MainZip / MainCountry | string | optional | Primary address |
| BillingContact / BillingContactPhone / BillingContactMobile / BillingContactFax / BillingContactEmail | string | optional | Billing contact details |
| BillingAddress1 / BillingAddress2 / BillingCity / BillingState / BillingZip / BillingCountry | string | optional | Billing address |
| TaxRate | number | optional | Tax rate percentage |
| TaxID | string | optional | Tax identification number |
| CurrencyID | string | optional | Currency identifier |
Update Client
Same fields as Create Client, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the client to update |
| All Create Client fields | optional | Any subset; TaxRate is applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"companyName": "Acme Corporation",
"description": "A sample client record",
"status": "Active",
"priority": "",
"active": true,
"terms": "Net 30",
"web": "https://acme.example.com",
"invoiceNote": "",
"thisCompany": "",
"taxRate": 0.00,
"taxId": "",
"mainContact": "John Smith",
"mainContactPhone": "555-1234",
"mainContactMobile": "",
"mainContactFax": "",
"mainContactEmail": "john@acme.com",
"mainAddress1": "123 Main St",
"mainAddress2": "",
"mainCity": "Springfield",
"mainState": "IL",
"mainZip": "62701",
"mainCountry": "USA",
"billingContact": "",
"billingContactPhone": "",
"billingContactMobile": "",
"billingContactFax": "",
"billingContactEmail": "",
"billingAddress1": "",
"billingAddress2": "",
"billingCity": "",
"billingState": "",
"billingZip": "",
"billingCountry": "",
"currencyId": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
},
"ErrorResults": ""
}
Subprojects New in 2.0.0
Create Subproject
| Field | Type | Description | |
|---|---|---|---|
| Name | string | required | Subproject name |
| ProjectId | GUID | required | Parent project identifier |
| ParentId | GUID | optional | Parent subproject identifier, for nested subprojects |
| Description | text | optional | Subproject description |
| Status | string | optional | e.g., Active, Complete |
| Priority | string | optional | Priority label |
| StartDate / FinishDate / LaunchDate | date | optional | ISO 8601 dates |
| QuotedDuration | string | optional | Quoted duration estimate |
| QuotedCost | string | optional | Quoted cost estimate |
| ClientRate | number | optional | Billing rate for this subproject |
| SalaryRate | number | optional | Salary rate for this subproject |
| Qty / QtyBuilt | number | optional | Quantity ordered / quantity built |
| UserText1 / UserText2 / UserText3 | string | optional | Custom user-defined text fields |
Update Subproject
Same fields as Create Subproject, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the subproject to update |
| All Create Subproject fields | optional | Any subset; rate/quantity fields are applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"name": "Phase 1",
"extendedName": "Website Redesign / Phase 1",
"description": "Initial discovery and wireframing",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"parentId": "",
"status": "Active",
"priority": "",
"active": true,
"level": 1,
"order": 1,
"projectCode": "",
"startDate": "2025-01-06",
"finishDate": "2025-01-31",
"launchDate": "",
"quotedDuration": "",
"quotedCost": "",
"clientRate": 0.00,
"salaryRate": 0.00,
"qty": 0.00,
"qtyBuilt": 0.00,
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
},
"ErrorResults": ""
}
Inventory New in 2.0.0
Create Inventory Item
| Field | Type | Description | |
|---|---|---|---|
| Name | string | required | Item name |
| Description | text | optional | Item description |
| Code | string | optional | Internal item code |
| Status | string | optional | e.g., Active, Inactive |
| UnitsType | string | optional | Unit of measure, e.g. each |
| BuyOrBuild | string | optional | Make-vs-buy flag |
| QtyInStock | number | optional | Current stock quantity |
| QtyWhenToReorder | number | optional | Reorder trigger threshold |
| QtyToReorder | number | optional | Quantity to reorder |
| CostUnit | number | optional | Internal cost per unit |
| CostClient | number | optional | Billable cost per unit |
| SKU / VendorSKU | string | optional | Stock keeping units |
| Vendor | string | optional | Vendor name |
| Manufacturer | string | optional | Manufacturer name |
| Location | string | optional | Storage location |
| Notes | text | optional | Free-text notes |
| UserText1 / UserText2 / UserText3 | string | optional | Custom user-defined text fields |
Update Inventory Item
Same fields as Create Inventory Item, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the inventory item to update |
| All Create Inventory Item fields | optional | Any subset; quantity and cost fields are applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "c56a4180-65aa-42ec-a945-5fd21dec0538",
"name": "Laptop",
"description": "Development laptop",
"code": "LAPTOP-001",
"status": "Active",
"active": true,
"qtyInStock": 5.00,
"qtyWhenToReorder": 2.00,
"qtyToReorder": 3.00,
"unitsType": "each",
"costUnit": 1200.00,
"costClient": 1500.00,
"leadTimeDays": 0,
"buyOrBuild": "",
"labor": 0.00,
"weight": 0.00,
"size": "",
"condition": "",
"sku": "LP-001",
"vendorSku": "",
"mfgSku": "",
"modelNum": "",
"serialNum": "",
"vendor": "",
"manufacturer": "",
"location": "Warehouse A",
"weblink": "",
"notes": "",
"userText1": "",
"userText2": "",
"userText3": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
},
"ErrorResults": ""
}
Categories New in 2.0.0
Create Category
| Field | Type | Description | |
|---|---|---|---|
| Name | string | required | Category name |
| Description | text | optional | Category description |
| ClientRate | number | optional | Billing rate for this category |
| SalaryRate | number | optional | Salary rate for this category |
| ProjectId | GUID | optional | Scope this category to a specific project |
| SubprojectId | GUID | optional | Scope this category to a specific subproject (dynamic dropdown) |
| UserId | GUID | optional | Scope this category to a specific user |
Update Category
Same fields as Create Category, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the category to update |
| All Create Category fields | optional | Any subset; ClientRate and SalaryRate are applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "9b2d3f1a-4e8c-4a7b-b92d-3f5e2a1c8d4e",
"name": "Development",
"description": "Software development work",
"active": true,
"clientRate": 0.00,
"salaryRate": 0.00,
"projectId": "",
"subprojectId": "",
"userId": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
},
"ErrorResults": ""
}
Invoices New in 2.0.0
Create Invoice
| Field | Type | Description | |
|---|---|---|---|
| ClientId | GUID | required | Client this invoice is billed to (dynamic dropdown) |
| ProjectId | GUID | optional | Project reference |
| SubprojectId | GUID | optional | Subproject reference (dynamic dropdown) |
| TaskId | GUID | optional | Task reference |
| InvoiceNum | string | optional | Invoice number, e.g. INV-2025-001 |
| DateSent | date | optional | ISO 8601 date |
| DueDate | date | optional | ISO 8601 date |
| Terms | integer | optional | Payment terms in days, e.g. 30. Distinct from Client's free-text Terms field. |
| PO | string | optional | Purchase order reference (text only) |
| Amount | number | optional | Invoice amount |
| TaxRate | number | optional | Tax rate percentage |
| InvoiceNote | text | optional | Note printed on the invoice |
| Notes | text | optional | Internal notes, not shown to the client |
| Representative | string | optional | Sales/account representative |
| StartRange / EndRange | date | optional | Billing period covered by this invoice |
Amount, TaxRate, and InvoiceNote were silently dropped and never saved. All three now persist correctly.
Update Invoice
Same fields as Create Invoice, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the invoice to update |
| All Create Invoice fields | optional | Any subset; Terms, Amount, and TaxRate are applied only when > 0 |
Response (both endpoints): subTotal, taxAmount, datePaid, paidInFull, amountPaid, and balanceDue are calculated by Standard Time® and cannot be set directly.
{
"Success": true,
"Data": {
"id": "e3d4c5b6-a7f8-4901-b234-c5d6e7f8a901",
"invoiceNum": "INV-2025-001",
"clientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"subprojectId": "",
"taskId": "",
"dateSent": "2025-01-31",
"dueDate": "2025-02-28",
"datePaid": "",
"paidInFull": false,
"subTotal": 5000.00,
"taxRate": 0.00,
"taxAmount": 0.00,
"amount": 5000.00,
"amountPaid": 0.00,
"balanceDue": 5000.00,
"terms": "30",
"po": "",
"invoiceNote": "Thank you for your business.",
"notes": "",
"representative": "",
"startRange": "2025-01-01",
"endRange": "2025-01-31",
"created": "2025-01-31T10:00:00Z",
"modified": "2025-01-31T10:00:00Z"
},
"ErrorResults": ""
}
Billing Rates New in 2.0.0
Create Billing Rate
| Field | Type | Description | |
|---|---|---|---|
| RateType | integer | optional | Numeric rate type code: 1 = by user, 2 = by project. Fixed in 2.0.0 — previously accepted as a string. |
| ClientRate | number | optional | Billable rate |
| SalaryRate | number | optional | Internal salary rate |
| StartDate / EndDate | date | optional | Date range this rate is effective |
| UserId | GUID | optional | Scope this rate to a specific user |
| ProjectId | GUID | optional | Scope this rate to a specific project |
| CategoryId | GUID | optional | Scope this rate to a specific category (dynamic dropdown) |
| RoleId | GUID | optional | Scope this rate to a specific role |
RateType as required at compose time, even though the server accepts a request with no fields set at all.
Update Billing Rate
Same fields as Create Billing Rate, plus:
| Field | Type | Description | |
|---|---|---|---|
| id | GUID | required | ID of the billing rate to update |
| All Create Billing Rate fields | optional | Any subset; RateType, ClientRate, and SalaryRate are applied only when > 0 |
Response (both endpoints):
{
"Success": true,
"Data": {
"id": "7f3d2a1b-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"rateType": 1,
"clientRate": 150.00,
"salaryRate": 75.00,
"startDate": "2025-01-01",
"endDate": "",
"userId": "",
"projectId": "",
"categoryId": "",
"roleId": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
},
"ErrorResults": ""
}
Trigger Reference
Standard Time® supports 22 REST Hook triggers — one for each combination of record type (project, task, time log, expense, user, client, subproject, inventory, category, invoice, billing rate) and event (created, updated). Each trigger uses the Subscribe/Unsubscribe endpoints above and fires a webhook payload to Zapier whenever the corresponding event occurs.
| Trigger Name | EventType | Fires when… |
|---|---|---|
| New Project | project.created | A project is created in Standard Time® |
| Updated Project | project.updated | A project's fields are modified |
| New Task | task.created | A task is created within a project |
| Updated Task | task.updated | A task's fields are modified |
| New Time Log | timelog.created | A time log is recorded |
| Updated Time Log | timelog.updated | A time log is modified |
| New Expense | expense.created | An expense record is created |
| Updated Expense | expense.updated | An expense record is modified |
| New User | user.created | A user account is created |
| Updated User | user.updated | A user account's details are modified |
| New Client New | client.created | A client is created |
| Updated Client New | client.updated | A client's fields are modified |
| New Subproject New | subproject.created | A subproject is created |
| Updated Subproject New | subproject.updated | A subproject's fields are modified |
| New Inventory Item New | inventory.created | An inventory item is created |
| Updated Inventory Item New | inventory.updated | An inventory item's fields are modified |
| New Category New | category.created | A category is created |
| Updated Category New | category.updated | A category's fields are modified |
| New Invoice New | invoice.created | An invoice is created |
| Updated Invoice New | invoice.updated | An invoice's fields are modified |
| New Billing Rate New | billingrate.created | A billing rate is created |
| Updated Billing Rate New | billingrate.updated | A billing rate's fields are modified |
Webhook delivery is asynchronous and non-blocking — it does not delay the Standard Time® operation that caused it. Each webhook is delivered via HTTP POST to the registered hookUrl. If the subscriber URL is unreachable, Zapier handles retries according to its own retry policy.
get_clients, get_subprojects, and get_categories are additional Zapier polling triggers, but they're marked hidden in the app and exist only to power the dynamic dropdown fields described above — they aren't available as Zap triggers in the Zapier editor.
Webhook Payload Schemas
Each webhook POST carries a JSON object. The event field identifies the trigger type; the remaining fields are the record's current state at the time of the event.
Project (created / updated)
{
"event": "project.created",
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"name": "Website Redesign",
"description": "Q1 redesign project",
"clientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "Active",
"priority": "",
"active": true,
"projectCode": "",
"billingType": "",
"clientRate": 0.00,
"salaryRate": 0.00,
"qty": 0.00,
"qtyBuilt": 0.00,
"startDate": "2025-01-06",
"finishDate": "2025-03-28",
"launchDate": "",
"deliveryDate": "",
"quotedDuration": "",
"quotedCost": "",
"po": "",
"userText1": "",
"userText2": "",
"userText3": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
Task (created / updated)
{
"event": "task.created",
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"name": "Design Mockups",
"description": "Initial wireframes",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"subprojectId": "",
"categoryId": "",
"clientId": "",
"status": "Active",
"priority": "",
"percentComplete": 0,
"completed": false,
"billable": true,
"startDate": "2025-01-07",
"finishDate": "2025-01-21",
"dueDate": "",
"completedDate": "",
"durationHours": 0.00,
"actualHours": 0.00,
"remainingHours": 0.00,
"costClient": 0.00,
"costSalary": 0.00,
"costClientActual": 0.00,
"costClientRemain": 0.00,
"costSalaryActual": 0.00,
"costSalaryRemain": 0.00,
"clientRate": 0.00,
"salaryRate": 0.00,
"quotedCost": "",
"qty": 0.00,
"qtyBuilt": 0.00,
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-07T09:00:00Z",
"modified": "2025-01-07T09:00:00Z"
}
Time Log (created / updated) renamed from Time Entry in 2.0.0
{
"event": "timelog.created",
"id": "e5f6a7b8-c9d0-1234-efab-234567890123",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"taskId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"subprojectId": "",
"categoryId": "",
"userId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"clientId": "",
"startTime": "2025-01-08T13:00:00Z",
"date": "2025-01-08",
"endTime": "2025-01-08T15:30:00Z",
"durationHours": 2.5,
"description": "Wireframe review session",
"billable": true,
"billed": false,
"approved": false,
"costClient": 0.00,
"costSalary": 0.00,
"clientRate": 0.00,
"salaryRate": 0.00,
"qty": 0.00,
"location": "",
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-08T15:30:00Z",
"modified": "2025-01-08T15:30:00Z"
}
Expense (created / updated)
{
"event": "expense.created",
"id": "f6a7b8c9-d0e1-2345-fabc-345678901234",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"clientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"subprojectId": "",
"categoryId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"userId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"expenseDate": "2025-01-09",
"amount": 124.50,
"price": 0.00,
"qty": 0.00,
"tax": 0.00,
"mileageRate": 0.00,
"distance": 0.00,
"odometerBegin": 0.00,
"odometerEnd": 0.00,
"description": "Conference travel",
"po": "",
"payee": "",
"checkNum": "",
"location": "",
"billable": true,
"billed": false,
"reimbursable": false,
"reimbursed": false,
"companyPaid": false,
"approved": false,
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-09T10:00:00Z",
"modified": "2025-01-09T10:00:00Z"
}
User (created / updated)
{
"event": "user.created",
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"username": "mwilson",
"email": "mwilson@example.com",
"name": "Mike Wilson",
"active": true,
"admin": false,
"contractor": false,
"exempt": false,
"workgroup": "",
"department": "",
"employeeNum": "",
"resourceType": "",
"hireDate": "",
"clientRate": 0.00,
"salaryRate": 0.00,
"mileageRate": 0.00,
"skills": "",
"userRole": "",
"managerId": "",
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-10T08:00:00Z",
"modified": "2025-01-10T08:00:00Z"
}
Client (created / updated) New in 2.0.0
{
"event": "client.created",
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"companyName": "Acme Corporation",
"description": "A sample client record",
"status": "Active",
"priority": "",
"active": true,
"terms": "Net 30",
"web": "https://acme.example.com",
"invoiceNote": "",
"thisCompany": "",
"taxRate": 0.00,
"taxId": "",
"mainContact": "John Smith",
"mainContactPhone": "555-1234",
"mainContactMobile": "",
"mainContactFax": "",
"mainContactEmail": "john@acme.com",
"mainAddress1": "123 Main St",
"mainAddress2": "",
"mainCity": "Springfield",
"mainState": "IL",
"mainZip": "62701",
"mainCountry": "USA",
"billingContact": "",
"billingContactPhone": "",
"billingContactMobile": "",
"billingContactFax": "",
"billingContactEmail": "",
"billingAddress1": "",
"billingAddress2": "",
"billingCity": "",
"billingState": "",
"billingZip": "",
"billingCountry": "",
"currencyId": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
Subproject (created / updated) New in 2.0.0
{
"event": "subproject.created",
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"name": "Phase 1",
"extendedName": "Website Redesign / Phase 1",
"description": "Initial discovery and wireframing",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"parentId": "",
"status": "Active",
"priority": "",
"active": true,
"level": 1,
"order": 1,
"projectCode": "",
"startDate": "2025-01-06",
"finishDate": "2025-01-31",
"launchDate": "",
"quotedDuration": "",
"quotedCost": "",
"clientRate": 0.00,
"salaryRate": 0.00,
"qty": 0.00,
"qtyBuilt": 0.00,
"userText1": "",
"userText2": "",
"userText3": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
Inventory (created / updated) New in 2.0.0
{
"event": "inventory.created",
"id": "c56a4180-65aa-42ec-a945-5fd21dec0538",
"name": "Laptop",
"description": "Development laptop",
"code": "LAPTOP-001",
"status": "Active",
"active": true,
"qtyInStock": 5.00,
"qtyWhenToReorder": 2.00,
"qtyToReorder": 3.00,
"unitsType": "each",
"costUnit": 1200.00,
"costClient": 1500.00,
"leadTimeDays": 0,
"buyOrBuild": "",
"labor": 0.00,
"weight": 0.00,
"size": "",
"condition": "",
"sku": "LP-001",
"vendorSku": "",
"mfgSku": "",
"modelNum": "",
"serialNum": "",
"vendor": "",
"manufacturer": "",
"location": "Warehouse A",
"weblink": "",
"notes": "",
"userText1": "",
"userText2": "",
"userText3": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
Category (created / updated) New in 2.0.0
{
"event": "category.created",
"id": "9b2d3f1a-4e8c-4a7b-b92d-3f5e2a1c8d4e",
"name": "Development",
"description": "Software development work",
"active": true,
"clientRate": 0.00,
"salaryRate": 0.00,
"projectId": "",
"subprojectId": "",
"userId": "",
"folder": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
Invoice (created / updated) New in 2.0.0
{
"event": "invoice.created",
"id": "e3d4c5b6-a7f8-4901-b234-c5d6e7f8a901",
"invoiceNum": "INV-2025-001",
"clientId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"projectId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"subprojectId": "",
"taskId": "",
"dateSent": "2025-01-31",
"dueDate": "2025-02-28",
"datePaid": "",
"paidInFull": false,
"subTotal": 5000.00,
"taxRate": 0.00,
"taxAmount": 0.00,
"amount": 5000.00,
"amountPaid": 0.00,
"balanceDue": 5000.00,
"terms": "30",
"po": "",
"invoiceNote": "Thank you for your business.",
"notes": "",
"representative": "",
"startRange": "2025-01-01",
"endRange": "2025-01-31",
"created": "2025-01-31T10:00:00Z",
"modified": "2025-01-31T10:00:00Z"
}
Billing Rate (created / updated) New in 2.0.0
{
"event": "billingrate.created",
"id": "7f3d2a1b-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"rateType": 1,
"clientRate": 150.00,
"salaryRate": 75.00,
"startDate": "2025-01-01",
"endDate": "",
"userId": "",
"projectId": "",
"categoryId": "",
"roleId": "",
"created": "2025-01-06T08:00:00Z",
"modified": "2025-01-06T08:00:00Z"
}
Security Notes
- Keys stored as SHA-256 hashes only — Standard Time® never persists a plaintext API key. The hash is computed at generation time; the original value is displayed once to the user and discarded.
- One active key per user — Generating a new key automatically revokes all previous keys for that user account.
- Header-based auth — Credentials travel in request headers, not in URLs or query strings (query string is a last-resort fallback only).
- Tenant isolation — Webhook subscriptions and API keys are scoped to the individual user. A webhook fires only to subscriptions registered by the authenticated user; it cannot access or trigger another user's Zaps. This applies uniformly across all 11 record types.
- HTTPS required — All communication must occur over HTTPS. Plain HTTP requests are rejected.
- No key retrieval — There is no endpoint that returns a plaintext API key. If a key is lost, generate a new one.
API Key Management (In-App)
API keys for the Zapier integration are managed inside Standard Time® — not through the Zapier dashboard. Navigate to Settings → Integrations → Zapier API Key to access the key management dialog.
Operations available in the dialog
| Action | Result |
|---|---|
| Generate New Key | Creates a new key and displays the full plaintext value once. Any existing active key is immediately revoked. Copy the key before closing the dialog — it cannot be retrieved again. |
| Revoke Key | Permanently deactivates the current key. Existing Zaps that use the revoked key will stop working immediately until reconfigured with a new key. |
| Set Trace Level | Controls the detail level written to the ZapierDebug audit log: 0 = off, 1 = errors only, 2 = warnings + errors, 3 = all activity. Use level 3 temporarily when diagnosing integration issues. |