openapi: 3.0.3 info: title: Nowsta Integration API version: '1.0.0' description: |- The Nowsta Integration API lets an approved partner platform publish event, shift and position data into Nowsta, along with the supporting system inputs — venues, clients, uniforms and workers — that enrich that data. The API is deliberately narrow: every resource is exposed through a single bulk "publications" endpoint that accepts an array of objects and performs create-or-update by the caller's own external `id`. There are no read (GET), PATCH or DELETE operations in the public integration surface. Semantics published by Nowsta and preserved here: * Every publication is a **POST, not a PATCH** — omitted fields are reset to their default (`null`), so callers must send the complete object on every update. * Every successful publication returns **202 Accepted** with the id of the queued job; Nowsta cannot guarantee a request is honoured on receipt (for example it will not remove shifts or shift slots that would unassign already-scheduled staff without coordinator confirmation). * Batches are limited to **32 items**; larger batches are rejected with 422 / error code 1203. * Publication requests for the same company are **queued and processed serially**, so callers are advised to issue requests in series rather than in parallel. * Access is **allow-listed**: Nowsta must approve a company before its token works, otherwise requests return 403 with error code 1101. DERIVATION NOTE — this document was transcribed by API Evangelist from Nowsta's own published Integration API reference (the Slate-generated site formerly at https://developer.nowsta.com/, captured at https://web.archive.org/web/20240603053309/https://developer.nowsta.com/). Every path, method, field name, type, nullability, constraint, status code and error code below appears verbatim in that reference. Nowsta does not publish a machine-readable specification; nothing here was invented. The live production API was probed on 2026-08-01 and confirmed to still serve these paths (unauthenticated POST returns `401 {"errors":[{"code":1000,"message":"Nil JSON web token"}]}`). contact: name: Nowsta url: https://www.nowsta.com/ x-evidence: generated: '2026-08-01' method: generated source: https://web.archive.org/web/20240603053309/https://developer.nowsta.com/ original_docs_host: https://developer.nowsta.com/ original_docs_status: DNS NXDOMAIN as of 2026-08-01 (developer docs host decommissioned) live_probe: url: https://api.nowsta.com/integrations/v1/events/publications method: POST http_status: 401 body: '{"errors":[{"code":1000,"message":"Nil JSON web token"}]}' fetched: '2026-08-01' externalDocs: description: Nowsta Integration API reference (archived) url: https://web.archive.org/web/20240603053309/https://developer.nowsta.com/ servers: - url: https://api.nowsta.com description: Production - url: https://api.nowsta-staging.com description: Staging / demo (access granted by Nowsta on request) tags: - name: Events description: Bulk publication of events and their nested shifts. - name: Venues description: Bulk publication of venues referenced by events. - name: Clients description: Bulk publication of clients referenced by events. - name: Uniforms description: Bulk publication of uniforms referenced by events. - name: Positions description: Bulk publication of positions referenced by shifts. - name: Workers description: Bulk publication of company users (workers). security: - bearerAuth: [] paths: /integrations/v1/events/publications: post: tags: [Events] operationId: publishEvents summary: Publish events and shifts description: >- Bulk create or update events and their nested shifts in a single call. The endpoint accepts up to 32 event publications per request. Each event is matched on the caller's own `id`. Because the action is a POST rather than a PATCH, any omitted field is reset to `null` — for example an event previously published with a `client_id` and then republished without one will have its client cleared. Nowsta advises keeping the number of shifts per event to roughly 20-30 or the request can become slow, especially in batch. Setting `archived_at` signals that the event has been cancelled or otherwise removed and should not appear in the Nowsta UI. requestBody: required: true content: application/json: schema: type: object required: [publications] properties: publications: type: array maxItems: 32 items: $ref: '#/components/schemas/EventPublication' example: publications: - id: '125A' name: My Example Event starts_at: '2015-11-04T09:20:22Z' ends_at: '2015-11-05T09:20:22Z' worker_instructions: Show up on time wearing nice clothing. time_zone: America/Los_Angeles admin_notes: Run payroll carefully for this event. supervisor_notes: Be sure to gather time and attendance data budget_cents: 45000 venue_id: '122B' uniform_id: '165X' client_id: 87RU invoice_cents: 65000 salesperson: John Smith archived_at: null display_id: E12345 shifts: - id: 15Q starts_at: '2015-11-04T09:20:22Z' ends_at: '2015-11-05T09:20:22Z' quantity: 8 position_id: 189F instructions: Bring your own bartending utensils. responses: '202': $ref: '#/components/responses/Accepted' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' /integrations/v1/venues/publications: post: tags: [Venues] operationId: publishVenues summary: Publish venues description: >- Bulk create or update venues on Nowsta, matched on the caller's own `id`. Venue names carry a uniqueness constraint in Nowsta, so a submitted name that collides with an existing one will be altered by Nowsta to preserve uniqueness — which is one reason the response is 202 rather than 200. Omitted fields are reset to `null`. requestBody: required: true content: application/json: schema: type: object required: [publications] properties: publications: type: array maxItems: 32 items: $ref: '#/components/schemas/VenuePublication' example: publications: - id: '125A' name: Jerry's Apartment address1: 129 West 81 Street address2: 5A city: New York state: NY zip: '10024' contact_phone_number: '2015556893' contact_email: JS@Kramerica.biz contact_full_name: Jerome Allen Seinfeld responses: '202': $ref: '#/components/responses/Accepted' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' /integrations/v1/clients/publications: post: tags: [Clients] operationId: publishClients summary: Publish clients description: >- Bulk create or update clients on Nowsta, matched on the caller's own `id`. Client names carry a uniqueness constraint in Nowsta, so a colliding name will be altered by Nowsta on ingest. Omitted fields are reset to `null`. requestBody: required: true content: application/json: schema: type: object required: [publications] properties: publications: type: array maxItems: 32 items: $ref: '#/components/schemas/ClientPublication' example: publications: - id: '125A' name: Vandelay Industries admin_notes: Great architecture firm supervisor_notes: Ask about the LaTex and LaTeX-related products. company_user_notes: Notes workers see contact_phone_number: '2015556893' contact_email: GC@Vandel.ly contact_full_name: Arthur Vandelay responses: '202': $ref: '#/components/responses/Accepted' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' /integrations/v1/uniforms/publications: post: tags: [Uniforms] operationId: publishUniforms summary: Publish uniforms description: >- Bulk create or update uniforms on Nowsta, matched on the caller's own `id`. Uniform names carry a uniqueness constraint in Nowsta, so a colliding name will be altered by Nowsta on ingest. Omitted fields are reset to `null`. requestBody: required: true content: application/json: schema: type: object required: [publications] properties: publications: type: array maxItems: 32 items: $ref: '#/components/schemas/UniformPublication' example: publications: - id: '125A' name: The puffy shirt description: Wear if you wanna be a pirate. responses: '202': $ref: '#/components/responses/Accepted' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' /integrations/v1/positions/publications: post: tags: [Positions] operationId: publishPositions summary: Publish positions description: >- Bulk create or update positions on Nowsta, matched on the caller's own `id`. Position names carry a uniqueness constraint in Nowsta, so a colliding name will be altered by Nowsta on ingest. Positions are referenced by shifts via `position_id`. Omitted fields are reset to `null`. requestBody: required: true content: application/json: schema: type: object required: [publications] properties: publications: type: array maxItems: 32 items: $ref: '#/components/schemas/PositionPublication' example: publications: - id: '125A' name: Comedian default_rate_cents: 3500 instructions: Make lots of jokes. description: The most important position. supervisor: false pay_code: 456-123 responses: '202': $ref: '#/components/responses/Accepted' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' /integrations/v1/workers/publications: post: tags: [Workers] operationId: publishWorkers summary: Publish workers description: >- Bulk create or update workers (company users) on Nowsta, matched on the caller's own `id`. Worker records are partly shared across every company a person works for, so update rules are restricted. Freely updatable via this endpoint - `start_date`, `notes`, `rank`, `pronouns`, `tablet_access_code`, `payroll_id`, and `email`/`phone_number` (the latter two only when the worker has not yet set up an account, by resending the same `id` with a different value). Updating `first_name`, `last_name`, `address1`, `address2`, `state`, `city`, `zip`, `birthday`, `emergency_contact_name`, `emergency_contact_phone_number`, `pronouns` or `nickname` desynchronizes the worker record between your company and the shared cross-company record; Nowsta then offers a re-sync, after which those fields can no longer be updated through this endpoint. requestBody: required: true content: application/json: schema: type: object required: [publications] properties: publications: type: array maxItems: 32 items: $ref: '#/components/schemas/CompanyUserPublication' example: publications: - id: 1W first_name: John last_name: Smith email: john@nowsta.com start_date: '2022-01-01T12:00:00Z' birthday: '2000-01-01' notes: The notes zip: '25554' nickname: a nickname emergency_contact_phone_number: '2125555555' city: City x rank: '1' pronouns: Her tablet_access_code: 123CODE state: NY phone_number: '2125555559' payroll_id: 123-PAY emergency_contact_name: Johnnys Saver address1: 129 West 81 Street address2: 122 West 84 Street responses: '202': $ref: '#/components/responses/Accepted' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' components: securitySchemes: bearerAuth: type: http scheme: bearer description: >- A per-company integration token issued by Nowsta and retrieved by the customer from the Nowsta UI, then entered into the integrating platform (for example on a settings page). The token is scoped to the single company that purchased the integration and only authorizes operations for that company. Send it as `Authorization: Bearer `. HTTPS is required; cross-origin browser requests are not permitted. Nowsta must first approve a company for the integration — requests on behalf of an unapproved company return 403 with error code 1101. responses: Accepted: description: >- Accepted and queued. Nowsta returns 202 because it cannot always guarantee that an update will be honoured on receipt — in particular it will not remove shifts or shift slots that would unassign staff without coordinator confirmation, and colliding venue/client/uniform/position names are altered to preserve uniqueness. The body carries the id of the queued job. content: application/json: schema: $ref: '#/components/schemas/PublicationAccepted' example: id: 123 Unauthorized: description: The request auth token is missing or invalid (error code 1000). content: application/json: schema: $ref: '#/components/schemas/ErrorsResponse' example: errors: - code: 1000 message: Nil JSON web token Forbidden: description: >- The provided auth token does not authorize this action — either the company has not been marked active for the integration (code 1101) or the request references objects belonging to another company (code 1100). content: application/json: schema: $ref: '#/components/schemas/ErrorsResponse' example: errors: - code: 1101 message: Access to integration forbidden UnprocessableEntity: description: >- Some input parameters are invalid or absent, or the batch exceeded the 32-item limit. The body mirrors the request structure - each invalid parameter is mapped to an array of error objects, keyed by the index of the offending entity in the original request (and nested under `shifts` for shift-level problems on the events endpoint). content: application/json: schema: $ref: '#/components/schemas/UnprocessableEntityBody' example: publications: '0': starts_at: - code: 1400 message: Starts at is after ends at shifts: '1': position_id: - code: 1300 message: Specified relation not found schemas: ErrorObject: type: object description: >- The ERROR_OBJ used throughout every error response - a numeric `code` plus a human-readable `message`. properties: code: type: integer description: Nowsta error code. See errors/nowsta-problem-types.yml for the published registry. example: 1201 message: type: string example: Parameter cannot be null ErrorsResponse: type: object properties: errors: type: array items: $ref: '#/components/schemas/ErrorObject' UnprocessableEntityBody: type: object description: >- Validation failures keyed by the index of the entity in the submitted `publications` array. Each field maps to an array of ERROR_OBJ. Nowsta publishes the shape but not a strict schema, so this is modelled as a free-form object rather than invented. properties: publications: type: object additionalProperties: true additionalProperties: true PublicationAccepted: type: object description: The id of the publication request, indicating receipt and insertion into Nowsta's job queue. properties: id: type: integer example: 123 ShiftPublication: type: object description: A shift nested inside an event publication (SHIFT_PUBLICATION). required: [id, starts_at, ends_at, quantity, position_id] properties: id: type: string maxLength: 255 description: Your own external identifier for the shift. starts_at: type: string format: date-time description: ISO 8601. Must be less than or equal to ends_at. ends_at: type: string format: date-time description: ISO 8601. quantity: type: integer minimum: 0 maximum: 1024 description: Number of workers required for the shift. position_id: type: string description: Must have a registered mapping with Nowsta (see publishPositions). instructions: type: string nullable: true EventPublication: type: object description: An event and its shifts (EVENT_PUBLICATION). required: [id, name, starts_at, ends_at, time_zone, shifts] properties: id: type: string maxLength: 255 description: Your own external identifier for the event. name: type: string maxLength: 255 starts_at: type: string format: date-time description: ISO 8601. Must be less than or equal to ends_at. ends_at: type: string format: date-time description: ISO 8601. time_zone: type: string description: >- Canonical tz database entry (e.g. "America/New_York"), not a UTC offset. shifts: type: array description: >- SHIFT_PUBLICATION objects. Nowsta advises no more than roughly 20-30 shifts per event. items: $ref: '#/components/schemas/ShiftPublication' venue_id: type: string nullable: true description: >- Must have a registered mapping with Nowsta. Mutually exclusive with the event-level venue fields (venue_name, address1, address2, city, state, zip) — sending both returns 422 with error code 1204. uniform_id: type: string nullable: true description: Must have a registered mapping with Nowsta. client_id: type: string nullable: true description: Must have a registered mapping with Nowsta. division: type: string nullable: true description: >- A plain string that maps to a Division object in Nowsta. An existing division with the same name is reused; otherwise the publication creates a new one. Divisions are an umbrella category for events and staff, typically reserved for enterprise customers with multiple regional operations — Nowsta asks to be consulted before this field is used. booking_status: type: string nullable: true archived_at: type: string format: date-time nullable: true description: >- Presence indicates the event has been cancelled or otherwise removed and should not appear in the Nowsta UI. display_id: type: string nullable: true admin_notes: type: string nullable: true worker_instructions: type: string nullable: true supervisor_notes: type: string nullable: true salesperson: type: string maxLength: 255 nullable: true budget_cents: type: integer minimum: 0 nullable: true invoice_cents: type: integer minimum: 0 nullable: true number_of_guests: type: integer nullable: true venue_name: type: string nullable: true description: Event-level venue field. Mutually exclusive with venue_id. address1: type: string nullable: true description: Event-level venue field. Mutually exclusive with venue_id. address2: type: string nullable: true description: Event-level venue field. Mutually exclusive with venue_id. city: type: string nullable: true description: Event-level venue field. Mutually exclusive with venue_id. state: type: string nullable: true description: Event-level venue field. Mutually exclusive with venue_id. zip: type: string nullable: true description: Event-level venue field. Mutually exclusive with venue_id. VenuePublication: type: object description: VENUE_PUBLICATION. required: [id, name] properties: id: type: string maxLength: 255 name: type: string maxLength: 255 address1: type: string maxLength: 255 nullable: true address2: type: string maxLength: 255 nullable: true city: type: string maxLength: 255 nullable: true state: type: string nullable: true description: 2 characters preferred (e.g. "NY"). zip: type: string maxLength: 255 nullable: true notes: type: string nullable: true contact_phone_number: type: string maxLength: 255 nullable: true contact_email: type: string maxLength: 255 nullable: true contact_full_name: type: string maxLength: 255 nullable: true ClientPublication: type: object description: CLIENT_PUBLICATION. required: [id, name] properties: id: type: string maxLength: 255 name: type: string admin_notes: type: string nullable: true supervisor_notes: type: string nullable: true company_user_notes: type: string nullable: true description: Notes that workers see. contact_phone_number: type: string maxLength: 255 nullable: true contact_email: type: string maxLength: 255 nullable: true contact_full_name: type: string maxLength: 255 nullable: true UniformPublication: type: object description: UNIFORM_PUBLICATION. required: [id, name] properties: id: type: string maxLength: 255 name: type: string maxLength: 255 description: type: string nullable: true PositionPublication: type: object description: POSITION_PUBLICATION. required: [id, name, supervisor] properties: id: type: string maxLength: 255 name: type: string maxLength: 255 default_rate_cents: type: integer nullable: true description: Must be positive. client_bill_rate_cents: type: integer nullable: true description: Must be positive. instructions: type: string nullable: true description: type: string nullable: true supervisor: type: boolean pay_code: type: string maxLength: 255 nullable: true CompanyUserPublication: type: object description: COMPANY_USER_PUBLICATION — a worker. required: [id, first_name, last_name, email] properties: id: type: string maxLength: 255 first_name: type: string maxLength: 255 last_name: type: string maxLength: 255 email: type: string maxLength: 255 start_date: type: string format: date nullable: true description: ISO 8601. birthday: type: string format: date nullable: true description: ISO 8601. notes: type: string nullable: true zip: type: string maxLength: 5 nullable: true nickname: type: string nullable: true emergency_contact_phone_number: type: string nullable: true description: Valid US phone number. city: type: string maxLength: 255 nullable: true rank: type: integer nullable: true pronouns: type: string nullable: true tablet_access_code: type: string nullable: true state: type: string maxLength: 255 nullable: true phone_number: type: string nullable: true description: Valid US phone number. payroll_id: type: string nullable: true emergency_contact_name: type: string nullable: true address1: type: string maxLength: 255 nullable: true description: >- Documented as `address_1` in the parameter table and as `address1` in the request example; transcribed here as published in the example payload. address2: type: string maxLength: 255 nullable: true description: >- Documented as `address_2` in the parameter table and as `address2` in the request example; transcribed here as published in the example payload.