openapi: 3.0.3 info: title: GoSpotCheck External API version: '1.0' x-generated: '2026-07-19' x-method: searched x-source: https://gsc.docs.apiary.io/ description: >- The GoSpotCheck (by FORM) External API lets developers build custom applications and integrations against a GoSpotCheck company account. It supports ongoing creates/updates to people, places, place groups, teams, catalogs and items, and pulling MissionResponse / TaskResponse data out of GoSpotCheck to build custom reports. All requests are RESTful over HTTPS, authenticated with an OAuth2 bearer token in the Authorization header. Responses use a standard envelope with `request`, `paging`, `data`, and `errors` hashes. Faithfully transcribed from the provider's published Apiary API Blueprint; not every field-level schema is modeled. contact: name: GoSpotCheck Support email: support@gospotcheck.com url: https://support.gospotcheck.com servers: - url: https://api.gospotcheck.com description: Production tags: - name: Places - name: PlaceGroups - name: Users - name: Teams - name: Missions - name: Tasks - name: MissionResponses - name: TaskResponses - name: UserPlaceAssignments - name: CustomViews - name: Catalogs - name: CatalogItems - name: AsyncJobs security: - oauth2Bearer: [] components: securitySchemes: oauth2Bearer: type: http scheme: bearer description: >- OAuth2 access token supplied as `Authorization: Bearer `. Tokens are issued by GoSpotCheck; contact your Customer Success Manager or support@gospotcheck.com to obtain one. parameters: page: name: page in: query description: Page number of results (defaults to 1). schema: { type: integer, default: 1 } perPage: name: per_page in: query description: Records per page (defaults to 25, max 200). schema: { type: integer, default: 25, maximum: 200 } sortBy: name: sort_by in: query description: Field to sort the index by. schema: { type: string } sortDirection: name: sort_direction in: query schema: { type: string, enum: [asc, desc] } include: name: include in: query description: Comma-separated related resources to embed (e.g. teams,place_groups). schema: { type: string } methods: name: methods in: query description: Comma-separated derived/additional data to include. schema: { type: string } async: name: _async in: query description: When true, run the index as an asynchronous CSV export job. schema: { type: boolean, default: false } schemas: RequestHash: type: object properties: status_code: { type: integer } status_message: { type: string } path: { type: string } method: { type: string } params: { type: object } PagingHash: type: object properties: current_page: { type: integer } previous_page: { type: integer, nullable: true } next_page: { type: integer, nullable: true } per_page: { type: integer } total_records: { type: integer } first_timestamp: { type: string } last_timestamp: { type: string } ErrorsHash: type: object description: Present only when status_code is in the 400 or 500 range. Envelope: type: object properties: request: { $ref: '#/components/schemas/RequestHash' } paging: { $ref: '#/components/schemas/PagingHash' } data: {} errors: { $ref: '#/components/schemas/ErrorsHash' } Place: type: object properties: id: { type: integer, description: Unique GSC id } name: { type: string } address: { type: string } city: { type: string } state: { type: string } postal_code: { type: string } country: { type: string, description: ISO3166-1 alpha-2 } custom_place_id: { type: string, nullable: true } status: { type: string, nullable: true, description: "null when enabled; 'disabled' when disabled" } disabled_at: { type: string, nullable: true } geocoding_disabled: { type: boolean } created_at: { type: string } updated_at: { type: string } PlaceGroup: type: object properties: id: { type: integer } name: { type: string } parent_id: { type: integer, nullable: true } created_at: { type: string } updated_at: { type: string } User: type: object properties: id: { type: integer } email: { type: string } first_name: { type: string } last_name: { type: string } phone: { type: string } company_membership_role: { type: string, description: company_admin | company_manager | company_user } team_id: { type: integer, nullable: true } disabled: { type: string, nullable: true } created_at: { type: string } updated_at: { type: string } Team: type: object properties: id: { type: integer } name: { type: string } parent_id: { type: integer, nullable: true } created_at: { type: string } updated_at: { type: string } Mission: type: object properties: id: { type: integer } name: { type: string } instructions: { type: string } maximum_responses_per_user: { type: integer, nullable: true } maximum_responses_per_location: { type: integer, nullable: true } state: { type: string, description: draft | published | stopped | completed | archived | versioned } enable_user_assigned_places: { type: boolean } version_identifier: { type: integer } version_number: { type: integer } started_at: { type: string, nullable: true } stopped_at: { type: string, nullable: true } completed_at: { type: string, nullable: true } archived_at: { type: string, nullable: true } created_by_id: { type: integer } updated_by_id: { type: integer } created_at: { type: string } updated_at: { type: string } Task: type: object properties: id: { type: integer } mission_id: { type: integer } title: { type: string } kind: { type: string } created_at: { type: string } updated_at: { type: string } MissionResponse: type: object properties: id: { type: integer } mission_id: { type: integer } place_id: { type: integer } user_id: { type: integer } created_at: { type: string } TaskResponse: type: object properties: id: { type: integer } task_id: { type: integer } mission_response_id: { type: integer } created_at: { type: string } Catalog: type: object properties: id: { type: integer } name: { type: string } created_at: { type: string } updated_at: { type: string } CatalogItem: type: object properties: id: { type: integer } catalog_id: { type: integer } name: { type: string } created_at: { type: string } updated_at: { type: string } UserPlaceAssignment: type: object properties: id: { type: integer } user_id: { type: integer } place_id: { type: integer } created_at: { type: string } AsyncJob: type: object properties: id: { type: integer } job_guid: { type: string } started_at: { type: string, nullable: true } completed_at: { type: string, nullable: true } failed_at: { type: string, nullable: true } error_type: { type: string, nullable: true } error_message: { type: string, nullable: true } download_url: { type: string, nullable: true } file_size: { type: integer, nullable: true } row_count: { type: integer, nullable: true } status_url: { type: string } created_at: { type: string } updated_at: { type: string } responses: Success: description: Standard success envelope. content: application/json: schema: { $ref: '#/components/schemas/Envelope' } BadRequest: description: Validation or field-format error (errors hash populated). content: application/json: schema: { $ref: '#/components/schemas/Envelope' } Unauthorized: description: Missing or invalid OAuth2 bearer token. content: application/json: schema: { $ref: '#/components/schemas/Envelope' } Forbidden: description: >- Forbidden. Also returned as `403 Forbidden (Rate Limit Exceeded)` when the 10 req/s or 100,000 req/day limit is exceeded. content: application/json: schema: { $ref: '#/components/schemas/Envelope' } NotFound: description: Resource not found. content: application/json: schema: { $ref: '#/components/schemas/Envelope' } Unprocessable: description: Unprocessable entity (model validation failed). content: application/json: schema: { $ref: '#/components/schemas/Envelope' } paths: /external/v1/places: get: operationId: listPlaces summary: List all places for the company tags: [Places] parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/perPage' - $ref: '#/components/parameters/sortBy' - $ref: '#/components/parameters/sortDirection' - $ref: '#/components/parameters/include' - $ref: '#/components/parameters/async' responses: '200': { $ref: '#/components/responses/Success' } '401': { $ref: '#/components/responses/Unauthorized' } '403': { $ref: '#/components/responses/Forbidden' } post: operationId: createPlaces summary: Create one place or multiple places tags: [Places] requestBody: content: application/json: schema: oneOf: - $ref: '#/components/schemas/Place' - type: array items: { $ref: '#/components/schemas/Place' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/places/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getPlace summary: Get a single place tags: [Places] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updatePlace summary: Update an existing place tags: [Places] requestBody: content: application/json: schema: { $ref: '#/components/schemas/Place' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } delete: operationId: disablePlace summary: Disable an existing place tags: [Places] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } /external/v1/place_groups: get: operationId: listPlaceGroups summary: List all place groups for the company tags: [PlaceGroups] parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/perPage' responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createPlaceGroup summary: Create a new place group tags: [PlaceGroups] requestBody: content: application/json: schema: { $ref: '#/components/schemas/PlaceGroup' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/place_groups/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getPlaceGroup summary: Get a single place group tags: [PlaceGroups] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updatePlaceGroup summary: Update an existing place group tags: [PlaceGroups] responses: '200': { $ref: '#/components/responses/Success' } delete: operationId: deletePlaceGroup summary: Delete an existing place group tags: [PlaceGroups] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/place_groups/{id}/add_places: put: operationId: addPlacesToPlaceGroup summary: Add places to a place group tags: [PlaceGroups] parameters: - name: id in: path required: true schema: { type: integer } - name: place_ids in: query schema: { type: string, description: Comma-separated place ids } responses: '200': { $ref: '#/components/responses/Success' } /external/v1/place_groups/{id}/remove_places: put: operationId: removePlacesFromPlaceGroup summary: Remove places from a place group tags: [PlaceGroups] parameters: - name: id in: path required: true schema: { type: integer } - name: place_ids in: query schema: { type: string } responses: '200': { $ref: '#/components/responses/Success' } /external/v1/users: get: operationId: listUsers summary: List users and user info tags: [Users] parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/perPage' - $ref: '#/components/parameters/include' responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createUsers summary: Create one or multiple users tags: [Users] requestBody: content: application/json: schema: oneOf: - $ref: '#/components/schemas/User' - type: array items: { $ref: '#/components/schemas/User' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/users/me: get: operationId: getCurrentUser summary: Get the current authenticated user tags: [Users] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/users/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getUser summary: Get a single user tags: [Users] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updateUser summary: Update an existing user tags: [Users] requestBody: content: application/json: schema: { $ref: '#/components/schemas/User' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/users/{id}/permissions: parameters: - name: id in: path required: true description: GSC user id or "me". schema: { type: string } get: operationId: getUserPermissions summary: View a user's manager permissions description: Only GoSpotCheck admins or company_admin users may view permissions. tags: [Users] responses: '200': { $ref: '#/components/responses/Success' } '403': { $ref: '#/components/responses/Forbidden' } put: operationId: updateUserPermissions summary: Update a user's manager permissions tags: [Users] responses: '200': { $ref: '#/components/responses/Success' } '403': { $ref: '#/components/responses/Forbidden' } /external/v1/teams: get: operationId: listTeams summary: List all teams for the company tags: [Teams] responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createTeam summary: Create a new team tags: [Teams] requestBody: content: application/json: schema: { $ref: '#/components/schemas/Team' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/teams/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getTeam summary: Get a single team tags: [Teams] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updateTeam summary: Update an existing team tags: [Teams] responses: '200': { $ref: '#/components/responses/Success' } delete: operationId: deleteTeam summary: Delete an existing team tags: [Teams] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/teams/{id}/add_users: put: operationId: addUsersToTeam summary: Add users to a team tags: [Teams] parameters: - name: id in: path required: true schema: { type: integer } - name: user_ids in: query schema: { type: string } responses: '200': { $ref: '#/components/responses/Success' } /external/v1/teams/{id}/remove_users: put: operationId: removeUsersFromTeam summary: Remove users from a team tags: [Teams] parameters: - name: id in: path required: true schema: { type: integer } - name: user_ids in: query schema: { type: string } responses: '200': { $ref: '#/components/responses/Success' } /external/v1/missions: get: operationId: listMissions summary: List missions and mission info tags: [Missions] parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/perPage' - $ref: '#/components/parameters/include' responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createMission summary: Create a mission tags: [Missions] requestBody: content: application/json: schema: { $ref: '#/components/schemas/Mission' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/missions/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getMission summary: Get a single mission tags: [Missions] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updateMission summary: Update an existing mission tags: [Missions] responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/missions/{mission_id}/tasks: parameters: - name: mission_id in: path required: true schema: { type: integer } get: operationId: listMissionTasks summary: Get tasks for a given mission tags: [Tasks] responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createMissionTasks summary: Create tasks and subtasks (sections) for a mission tags: [Tasks] responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/missions/{mission_id}/tasks/{id}: parameters: - name: mission_id in: path required: true schema: { type: integer } - name: id in: path required: true schema: { type: integer } put: operationId: updateMissionTask summary: Update an existing task tags: [Tasks] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/mission_responses: get: operationId: listMissionResponses summary: List mission responses (read-only) tags: [MissionResponses] parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/perPage' - $ref: '#/components/parameters/include' - $ref: '#/components/parameters/async' responses: '200': { $ref: '#/components/responses/Success' } /external/v1/mission_responses/{id}: get: operationId: getMissionResponse summary: Get a single mission response (read-only) tags: [MissionResponses] parameters: - name: id in: path required: true schema: { type: integer } responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } /external/v1/task_responses: get: operationId: listTaskResponses summary: List task responses (read-only) tags: [TaskResponses] parameters: - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/perPage' - $ref: '#/components/parameters/include' - $ref: '#/components/parameters/async' responses: '200': { $ref: '#/components/responses/Success' } /external/v1/task_responses/{id}: get: operationId: getTaskResponse summary: Get a single task response (read-only) tags: [TaskResponses] parameters: - name: id in: path required: true schema: { type: integer } responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } /external/v1/user_place_assignments: get: operationId: listUserPlaceAssignments summary: List user-place assignments tags: [UserPlaceAssignments] responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createUserPlaceAssignments summary: Create user-place assignments tags: [UserPlaceAssignments] responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/user_place_assignments/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getUserPlaceAssignment summary: Get a single user-place assignment tags: [UserPlaceAssignments] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } delete: operationId: deleteUserPlaceAssignment summary: Delete a user-place assignment tags: [UserPlaceAssignments] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/custom_views: get: operationId: listCustomViews summary: List custom views (read-only) tags: [CustomViews] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/custom_views/{id}: get: operationId: getCustomView summary: Query a custom view (read-only) tags: [CustomViews] parameters: - name: id in: path required: true schema: { type: integer } responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } /external/v1/custom_views/{id}/metadata: get: operationId: getCustomViewMetadata summary: Get metadata for a custom view tags: [CustomViews] parameters: - name: id in: path required: true schema: { type: integer } responses: '200': { $ref: '#/components/responses/Success' } /external/v1/catalogs: get: operationId: listCatalogs summary: List catalogs tags: [Catalogs] responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createCatalog summary: Create a catalog tags: [Catalogs] requestBody: content: application/json: schema: { $ref: '#/components/schemas/Catalog' } responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/catalogs/{id}: parameters: - name: id in: path required: true schema: { type: integer } get: operationId: getCatalog summary: Get a single catalog with its items tags: [Catalogs] responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' } put: operationId: updateCatalog summary: Update an existing catalog tags: [Catalogs] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/catalogs/{catalog_id}/items: parameters: - name: catalog_id in: path required: true schema: { type: integer } get: operationId: listCatalogItems summary: List catalog items tags: [CatalogItems] responses: '200': { $ref: '#/components/responses/Success' } post: operationId: createCatalogItems summary: Create catalog items tags: [CatalogItems] responses: '200': { $ref: '#/components/responses/Success' } '422': { $ref: '#/components/responses/Unprocessable' } /external/v1/catalogs/{catalog_id}/items/{id}: parameters: - name: catalog_id in: path required: true schema: { type: integer } - name: id in: path required: true schema: { type: integer } put: operationId: updateCatalogItem summary: Update a catalog item tags: [CatalogItems] responses: '200': { $ref: '#/components/responses/Success' } delete: operationId: deleteCatalogItem summary: Delete a catalog item tags: [CatalogItems] responses: '200': { $ref: '#/components/responses/Success' } /external/v1/async_jobs/csv_exports/{job_guid}/status: get: operationId: getAsyncCsvExportStatus summary: Check the status of an asynchronous CSV export job tags: [AsyncJobs] parameters: - name: job_guid in: path required: true schema: { type: string } responses: '200': { $ref: '#/components/responses/Success' } '404': { $ref: '#/components/responses/NotFound' }