Nowsta Integration API

Allow-listed partner API for publishing workforce data into Nowsta. Six bulk "publications" endpoints - events (with nested shifts), venues, clients, uniforms, positions and workers - each accepting up to 32 objects per request and performing create-or-update keyed on the caller's own external id. Authentication is a per-company bearer token that the customer retrieves from the Nowsta UI; Nowsta must approve a company before its token is active. Every successful publication returns 202 Accepted with a queued-job id, because Nowsta will not apply changes that would unassign already-scheduled staff without coordinator confirmation. There are no read, PATCH or DELETE operations in the public surface, and no documented webhook or event stream.

Documentation

Specifications

Other Resources

OpenAPI Specification

nowsta-integration-openapi.yml Raw ↑
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 <token>`. 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.