openapi: 3.1.0 info: title: Metamaps Integration API version: 2.0.0 description: | An integration API for operating Metamaps (metamaps.jp) from external systems. Using authentication with an **API key** issued per map, you can manage POIs (spots) and customer-managed spot SubIds in v2, retrieve and update current congestion values that are independent of the POI body—either for all spots at once or one at a time— and read, create, update, and delete event information (timetables). From `/api/integrations/v2/maps/{slug}` you can manage POIs and pictograms, user images, sponsor ads, SubIds, booth numbers, and spot operational status with the three permissions Read / Write / Delete. There is no per-map generation flag; every map can use this API. The legacy `/api/integrations/maps/{slug}` API is not provided. ## Authentication All endpoints take a **per-map API key** in the `X-Api-Key` request header. The POI API and the congestion value API use the same per-map integration API key `pmk_*`. ``` X-Api-Key: pmk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` You can view and reissue the API key under **Advanced settings -> Integration API key** in the Metamaps admin console. Reissuing **invalidates the old key immediately**. > Use credentials (API keys) for server-to-server communication only; never embed them in browsers or public clients. ## Permissions Set the following permissions on the API key in the admin console. In v2 the three permissions can be set independently, and turning all of them OFF disables v2. - **Read**: Retrieve information from the target API - **Write**: Create, update, and unset through the target API - **Delete**: Explicit deletion of physical/linked spots, user image masters, and events The same three permissions apply in common to POI management API v2, the congestion value API, and the event management API. If a valid API key lacks the required permission, **403 `forbidden`** is returned. ## Existence concealment Even when the key is invalid or unissued, or the `slug` does not exist, the response is uniformly **401 `unauthorized`** with no distinction (in order to conceal whether a map exists). ## Rate limits Each integration API applies a per-IP abuse cap before authentication and, after successful authentication, a limit per API key fingerprint + IP address. The post-authentication limits are counted across all servers. | API | Post-authentication limit | |---|---| | POI management API v2 (all endpoints except `congestion-values` and `spot-statuses`) | **60 requests / minute** | | Spot operational status (`spot-statuses`) with `pmk_*` | Counted in the same **60 requests / minute** quota as the POI management API | | Event management API | **60 requests / minute**, in a quota separate from the POI management API (so that event updates are not dropped by periodic POI synchronization) | | Congestion value API (`congestion-values`) | **10 requests / minute** | The spot operational status endpoints called with `sst_*` allow 300 requests/min/IP. For periodic synchronization, read with the paginated list endpoints (up to 150 records per page) and write only the records that changed. `429 Too Many Requests` is returned when the limit is exceeded, with a `Retry-After` header giving the number of seconds to wait before retrying (1–60): for the post-authentication limits, the time until the current one-minute window ends; for the pre-authentication abuse cap, the full window length (60). contact: name: Boldright Inc. url: 'https://metamaps.jp' license: name: Proprietary url: 'https://metamaps.jp' servers: - url: 'https://metamaps.jp' description: Production tags: - name: v2-control description: 'v2 capabilities, reference master data, and asynchronous operations' - name: v2-spots description: 'Read, create, update, convert, and delete all business fields of POIs and pictograms' - name: v2-images description: User image masters and read-only preset images - name: spot-statuses description: The legacy general-purpose spot operational status. A separate contract from the new `congestion-values` current congestion values. Available with pmk_* or a scope-restricted sst_* - name: congestion description: 'Retrieve and update current congestion values, independent of the POI body, using the shared integration API key pmk_*' - name: events description: 'Read, create, update, and delete event information (timetables), and configure the visibility switch and publication period' - name: assets description: Image assets (stable URLs) paths: '/api/integrations/v2/maps/{slug}/congestion-values': get: tags: - congestion operationId: GetCongestionValues summary: Retrieve current congestion values for assigned POIs description: | Retrieves the current congestion values that are enabled and assigned in the admin console, together with the active definitions needed to interpret them. Definition masters and POI assignments cannot be changed. `mapSpotId` is an opaque string matched exactly against the Spot StableKey within the map. Read permission on the integration API key `pmk_*` is required. parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] responses: '200': description: Retrieved successfully content: application/json: schema: $ref: '#/components/schemas/CongestionValuesResponse' examples: default: $ref: '#/components/examples/CongestionValuesExample' '401': description: 'Invalid or unissued key, nonexistent slug, archived map, or disabled tenant.' content: application/json: schema: $ref: '#/components/schemas/ApiError' '403': description: The integration API key does not have Read permission. content: application/json: schema: $ref: '#/components/schemas/ApiError' '409': description: The map's congestion source switch is OFF (`congestion_disabled`). content: application/json: schema: $ref: '#/components/schemas/ApiError' '429': description: 'Exceeded the pre-authentication IP abuse cap, or the post-authentication limit of 10 requests/min per key fingerprint + IP.' headers: Retry-After: $ref: '#/components/headers/RetryAfter' put: tags: - congestion operationId: UpdateCongestionValues summary: 'Atomically update up to 2,000 current congestion values' description: | Specify `mapSpotId`, `expectedDefinitionKey` to confirm the match with the assigned definition, and `value` as an integer or null. null means hidden. This API does not change definition masters or POI assignments. If even one entry is invalid, no current values, statistics, or publications are changed. Linked POIs propagate to all physical siblings. Specifying the same logical spot with different values results in `conflicting_linked_spot_updates`. Write permission on the integration API key `pmk_*` and an `Idempotency-Key` of 1-100 characters are required. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IdempotencyKey' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CongestionBatchUpdateRequest' examples: default: $ref: '#/components/examples/CongestionUpdateExample' responses: '200': description: Updated successfully content: application/json: schema: $ref: '#/components/schemas/CongestionBatchUpdateResponse' '400': description: 'Invalid count, duplicates, link conflict, value range, expectedDefinitionKey, or similar.' content: application/json: schema: $ref: '#/components/schemas/ApiError' '401': description: Authentication failed. content: application/json: schema: $ref: '#/components/schemas/ApiError' '403': description: The integration API key does not have Write permission. content: application/json: schema: $ref: '#/components/schemas/ApiError' '404': description: No POI was found for the specified mapSpotId. content: application/json: schema: $ref: '#/components/schemas/ApiError' '409': description: 'Idempotency key reuse, state conflict, source switch OFF, an assignment/definition conflict, or a POI managed by the AI camera integration (`congestion_camera_managed`).' content: application/json: schema: $ref: '#/components/schemas/ApiError' '429': description: Rate limit exceeded. headers: Retry-After: $ref: '#/components/headers/RetryAfter' '/api/integrations/v2/maps/{slug}/congestion-values/{mapSpotId}': get: tags: - congestion operationId: GetCongestionValue summary: Retrieve the current congestion values for one POI parameters: - $ref: '#/components/parameters/MapSlug' - name: mapSpotId in: path required: true description: Spot StableKey within the map. An opaque string matched exactly. schema: type: string minLength: 1 example: 6Y6SSBY5 security: - ApiKeyAuth: [] responses: '200': description: Retrieved successfully content: application/json: schema: $ref: '#/components/schemas/CongestionValuesResponse' '401': description: Authentication failed. content: application/json: schema: $ref: '#/components/schemas/ApiError' '403': description: The integration API key does not have Read permission. content: application/json: schema: $ref: '#/components/schemas/ApiError' '404': description: No assigned POI was found. content: application/json: schema: $ref: '#/components/schemas/ApiError' '409': description: The map's congestion source switch is OFF. content: application/json: schema: $ref: '#/components/schemas/ApiError' '429': description: Rate limit exceeded. headers: Retry-After: $ref: '#/components/headers/RetryAfter' put: tags: - congestion operationId: UpdateCongestionValue summary: Update the current congestion value for one POI parameters: - $ref: '#/components/parameters/MapSlug' - name: mapSpotId in: path required: true schema: type: string minLength: 1 example: 6Y6SSBY5 - $ref: '#/components/parameters/IdempotencyKey' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CongestionSingleUpdateRequest' example: expectedDefinitionKey: 9M5Q2X7R value: 15 responses: '200': description: Updated successfully content: application/json: schema: $ref: '#/components/schemas/CongestionSingleUpdateResponse' '400': description: Invalid expectedDefinitionKey or value. content: application/json: schema: $ref: '#/components/schemas/ApiError' '401': description: Authentication failed. content: application/json: schema: $ref: '#/components/schemas/ApiError' '403': description: The integration API key does not have Write permission. content: application/json: schema: $ref: '#/components/schemas/ApiError' '404': description: No POI was found for the specified mapSpotId. content: application/json: schema: $ref: '#/components/schemas/ApiError' '409': description: 'Idempotency key reuse, state conflict, source switch OFF, an assignment/definition conflict, or a POI managed by the AI camera integration (`congestion_camera_managed`).' content: application/json: schema: $ref: '#/components/schemas/ApiError' '429': description: 'Exceeded the pre-authentication IP abuse cap, or the post-authentication limit of 10 requests/min per key fingerprint + IP.' headers: Retry-After: $ref: '#/components/headers/RetryAfter' '/api/integrations/v2/maps/{slug}/capabilities': get: tags: - v2-control operationId: GetPoiManagementCapabilitiesV2 summary: 'Retrieve v2 permissions, features, and limits' parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] responses: '200': description: 'Current Read / Write / Delete permissions, feature flags, and API limits.' content: application/json: schema: $ref: '#/components/schemas/V2Capabilities' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/references': get: tags: - v2-control operationId: GetPoiManagementReferencesV2 summary: Retrieve reference master data for spot updates parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] responses: '200': description: 'MapGroups, floors, categories, display sets, and field definitions. Changing these themselves is out of scope.' content: application/json: schema: $ref: '#/components/schemas/V2References' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/spots': get: tags: - v2-spots operationId: ListManagedSpotsV2 summary: Retrieve POIs and pictograms with paging parameters: - $ref: '#/components/parameters/MapSlug' - name: type in: query schema: type: string enum: - poi - icon - name: floorId in: query schema: type: string format: uuid - name: categoryId in: query schema: type: string format: uuid - name: updatedAfter in: query schema: type: string format: date-time - name: q in: query schema: type: string - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 150 default: 50 security: - ApiKeyAuth: [] responses: '200': description: A list including hidden spots. content: application/json: schema: $ref: '#/components/schemas/V2SpotPage' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' post: tags: - v2-spots operationId: CreateManagedSpotV2 summary: Create a POI or pictogram description: | Write permission and an `Idempotency-Key` are required. Well-typed input for a feature that is OFF is neither saved nor fetched externally, and is reported via `ignoredFields`. If a new external image must be fetched, 202 and an operation are returned. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IdempotencyKey' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/V2SpotCreateRequest' responses: '201': description: Created synchronously. content: application/json: schema: $ref: '#/components/schemas/V2Spot' '202': $ref: '#/components/responses/OperationAccepted' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/ImageRejected' '429': $ref: '#/components/responses/RateLimited' '503': $ref: '#/components/responses/ImageUnavailable' '/api/integrations/v2/maps/{slug}/spots/{mapSpotId}': get: tags: - v2-spots operationId: GetManagedSpotV2 summary: Retrieve all business fields of a POI or pictogram parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' security: - ApiKeyAuth: [] responses: '200': description: Retrieved successfully. The response header and the `eTag` in the body are the same opaque value. headers: ETag: schema: type: string content: application/json: schema: $ref: '#/components/schemas/V2Spot' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '404': $ref: '#/components/responses/SpotNotFound' '429': $ref: '#/components/responses/RateLimited' patch: tags: - v2-spots operationId: PatchManagedSpotV2 summary: Partially update a POI or pictogram description: 'Omitted fields are kept, null on a nullable field clears it, and arrays are fully replaced. Linked siblings and related sets are updated atomically.' parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/V2SpotPatchRequest' responses: '200': description: 'Update complete. `changed:false` when the values are identical or all input was ignored.' content: application/json: schema: $ref: '#/components/schemas/V2Spot' '202': $ref: '#/components/responses/OperationAccepted' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': $ref: '#/components/responses/SpotNotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/ImageRejected' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '503': $ref: '#/components/responses/ImageUnavailable' delete: tags: - v2-spots operationId: DeletePhysicalSpotV2 summary: Delete only the specified physical spot parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] responses: '200': description: The ID of the deleted physical spot. content: application/json: schema: $ref: '#/components/schemas/V2SpotDeleteResult' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/DeleteForbidden' '404': $ref: '#/components/responses/SpotNotFound' '409': $ref: '#/components/responses/Conflict' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/spots/{mapSpotId}/convert': post: tags: - v2-spots operationId: ConvertManagedSpotV2 summary: Convert between POI and pictogram description: Type-specific stored values are not discarded. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - to properties: to: type: string enum: - poi - icon responses: '200': description: The converted spot. content: application/json: schema: $ref: '#/components/schemas/V2Spot' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': $ref: '#/components/responses/SpotNotFound' '409': $ref: '#/components/responses/Conflict' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/spots/{mapSpotId}/linked': delete: tags: - v2-spots operationId: DeleteLinkedSpotV2 summary: Delete all physical spots of the same logical spot parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] responses: '200': description: The IDs of all deleted physical spots. content: application/json: schema: $ref: '#/components/schemas/V2SpotDeleteResult' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/DeleteForbidden' '404': $ref: '#/components/responses/SpotNotFound' '409': $ref: '#/components/responses/Conflict' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/images': get: tags: - v2-images operationId: ListManagedImagesV2 summary: Retrieve user images and preset images parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] responses: '200': description: 'Presets have `readOnly:true` and no ETag.' content: application/json: schema: $ref: '#/components/schemas/V2ImageList' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' post: tags: - v2-images operationId: CreateManagedImageV2 summary: Create a user image master from an HTTPS URL parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IdempotencyKey' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/V2ImageCreateRequest' responses: '201': description: Created synchronously by reusing an existing asset. content: application/json: schema: $ref: '#/components/schemas/V2Image' '202': $ref: '#/components/responses/OperationAccepted' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/ImageRejected' '429': $ref: '#/components/responses/RateLimited' '503': $ref: '#/components/responses/ImageUnavailable' '/api/integrations/v2/maps/{slug}/images/{iconKey}': get: tags: - v2-images operationId: GetManagedImageV2 summary: Retrieve an image master parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IconKey' security: - ApiKeyAuth: [] responses: '200': description: Retrieved successfully. content: application/json: schema: $ref: '#/components/schemas/V2Image' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '404': $ref: '#/components/responses/ImageNotFound' '429': $ref: '#/components/responses/RateLimited' patch: tags: - v2-images operationId: PatchManagedImageV2 summary: Partially update a user image master parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IconKey' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/V2ImagePatchRequest' responses: '200': description: 'Metadata updated, or an existing asset reused.' content: application/json: schema: $ref: '#/components/schemas/V2Image' '202': $ref: '#/components/responses/OperationAccepted' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': $ref: '#/components/responses/ImageNotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/ImageRejected' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '503': $ref: '#/components/responses/ImageUnavailable' delete: tags: - v2-images operationId: DeleteManagedImageV2 summary: Delete a user image master description: '`confirmInUse=true` is required while the image is in use. A spot''s iconKey / logoIconKey is kept as a soft reference that surfaces a dangling-reference warning.' parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IconKey' - $ref: '#/components/parameters/IfMatch' - name: confirmInUse in: query schema: type: boolean default: false security: - ApiKeyAuth: [] responses: '200': description: Deletion result. content: application/json: schema: type: object required: - iconKey - affectedSpots properties: iconKey: type: string affectedSpots: type: integer minimum: 0 '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/DeleteForbidden' '404': $ref: '#/components/responses/ImageNotFound' '409': $ref: '#/components/responses/Conflict' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/operations/{operationId}': get: tags: - v2-control operationId: GetPoiMutationOperationV2 summary: Retrieve the status of an asynchronous image mutation parameters: - $ref: '#/components/parameters/MapSlug' - name: operationId in: path required: true schema: type: string format: uuid security: - ApiKeyAuth: [] responses: '200': description: Operation status. The `error` returned on failure contains no input URLs or internal keys. content: application/json: schema: $ref: '#/components/schemas/V2Operation' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': description: The operation does not exist in the same map. '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/spot-statuses': get: tags: - spot-statuses operationId: ListSpotStatusesV2 summary: Retrieve the operational status and definitions of all spots parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] - StaffTokenAuth: [] responses: '200': description: 'With sst_*, results are narrowed to the AND of the permitted spots and the permitted status set.' content: application/json: schema: $ref: '#/components/schemas/SpotStatusResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' put: tags: - spot-statuses operationId: UpdateSpotStatusesV2 summary: 'Atomically update the operational status of up to 2,000 spots' description: | When the congestion switch of the map is OFF in the admin console (`features.congestionEnabled=false` from `/capabilities`), well-typed input is neither validated nor saved, is reported in `ignoredFields` with `feature: showCongestion`, and freshness is not advanced. parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] - StaffTokenAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SpotStatusBatchRequest' responses: '200': description: The status after the update. content: application/json: schema: $ref: '#/components/schemas/SpotStatusResponse' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/v2/maps/{slug}/spot-statuses/{mapSpotId}': get: tags: - spot-statuses operationId: GetSpotStatusV2 summary: Retrieve the operational status of one spot parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' security: - ApiKeyAuth: [] - StaffTokenAuth: [] responses: '200': description: Retrieved successfully. content: application/json: schema: $ref: '#/components/schemas/SpotStatusResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '404': $ref: '#/components/responses/SpotNotFound' '429': $ref: '#/components/responses/RateLimited' put: tags: - spot-statuses operationId: UpdateSpotStatusV2 summary: Update the operational status of one spot parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/MapSpotId' security: - ApiKeyAuth: [] - StaffTokenAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SpotStatusSingleRequest' responses: '200': description: The status after the update. content: application/json: schema: $ref: '#/components/schemas/SpotStatusResponse' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': $ref: '#/components/responses/SpotNotFound' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/events/maps/{slug}/capabilities': get: tags: - events operationId: GetEventCapabilities summary: 'Retrieve event integration permissions, feature status, and limits' description: | Returns the three API key permissions, the visibility status and publication period of the events feature, the limits, and the related endpoints. `settingsETag` can be passed as-is to `If-Match` on `PATCH /settings`. parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] responses: '200': description: Retrieved successfully. content: application/json: schema: $ref: '#/components/schemas/EventCapabilities' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/events/maps/{slug}/settings': get: tags: - events operationId: GetEventSettings summary: Retrieve the event visibility switch and publication period parameters: - $ref: '#/components/parameters/MapSlug' security: - ApiKeyAuth: [] responses: '200': description: Retrieved successfully. content: application/json: schema: $ref: '#/components/schemas/EventSettings' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' patch: tags: - events operationId: UpdateEventSettings summary: Update the event visibility switch and publication period description: | Omitted fields keep their current values, and `null` is stored as unlimited (publication period only). While `eventsEnabled=false` or outside the publication period, the "Events" item in the public menu and the public API do not respond. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EventSettingsPatchRequest' responses: '200': description: The settings after the update. content: application/json: schema: $ref: '#/components/schemas/EventSettings' '400': $ref: '#/components/responses/EventValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '409': $ref: '#/components/responses/EventConflict' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/events/maps/{slug}/events': get: tags: - events operationId: ListEvents summary: Retrieve events with paging description: | Events that are not published (`isEnabled=false`) are returned as well. The sort order is start time, end time, title, then ID. parameters: - $ref: '#/components/parameters/MapSlug' - name: from in: query description: Returns only events that overlap at or after this time (UTC). schema: type: string format: date-time - name: to in: query description: Returns only events that overlap before this time (UTC). schema: type: string format: date-time - name: updatedAfter in: query description: For differential synchronization. Returns only events updated after this time (UTC). schema: type: string format: date-time - name: isEnabled in: query schema: type: boolean - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 150 default: 50 security: - ApiKeyAuth: [] responses: '200': description: The list. content: application/json: schema: $ref: '#/components/schemas/EventPage' '400': $ref: '#/components/responses/EventValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '429': $ref: '#/components/responses/RateLimited' post: tags: - events operationId: CreateEvent summary: Create an event description: | Up to 500 events per map. When `banner.url` is specified, an external image is fetched, so **202** and an `operationId` are returned; collect the result with `GET /operations/{operationId}`. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/IdempotencyKey' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EventCreateRequest' responses: '201': description: The created event. content: application/json: schema: $ref: '#/components/schemas/Event' '202': $ref: '#/components/responses/OperationAccepted' '400': $ref: '#/components/responses/EventValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '409': $ref: '#/components/responses/EventConflict' '422': $ref: '#/components/responses/ImageRejected' '429': $ref: '#/components/responses/RateLimited' '503': $ref: '#/components/responses/ImageUnavailable' '/api/integrations/events/maps/{slug}/events/{eventId}': get: tags: - events operationId: GetEvent summary: Retrieve a single event parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/EventId' security: - ApiKeyAuth: [] responses: '200': description: A single event. The same value is returned in the `ETag` header and in `eTag`. headers: ETag: schema: type: string content: application/json: schema: $ref: '#/components/schemas/Event' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/ReadForbidden' '404': $ref: '#/components/responses/EventNotFound' '429': $ref: '#/components/responses/RateLimited' patch: tags: - events operationId: UpdateEvent summary: Partially update an event description: | Omitted fields keep their current values, `null` clears them, and arrays are fully replaced. `startsAt` and `endsAt` may each be specified on their own, but the resulting combination must satisfy the period rules. When `banner.url` is specified, **202** and an `operationId` are returned. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/EventId' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EventPatchRequest' responses: '200': description: The event after the update. headers: ETag: schema: type: string content: application/json: schema: $ref: '#/components/schemas/Event' '202': $ref: '#/components/responses/OperationAccepted' '400': $ref: '#/components/responses/EventValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': $ref: '#/components/responses/EventNotFound' '409': $ref: '#/components/responses/EventConflict' '422': $ref: '#/components/responses/ImageRejected' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '503': $ref: '#/components/responses/ImageUnavailable' delete: tags: - events operationId: DeleteEvent summary: Delete an event description: | Deletes the event itself, its dedicated banner, body images not referenced by other events, and its translations and translation jobs. No endpoint is provided for deleting all events of a map at once. parameters: - $ref: '#/components/parameters/MapSlug' - $ref: '#/components/parameters/EventId' - $ref: '#/components/parameters/IfMatch' security: - ApiKeyAuth: [] responses: '204': description: Deleted. '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/DeleteForbidden' '404': $ref: '#/components/responses/EventNotFound' '409': $ref: '#/components/responses/EventConflict' '428': $ref: '#/components/responses/PreconditionRequired' '429': $ref: '#/components/responses/RateLimited' '/api/integrations/events/maps/{slug}/operations/{operationId}': get: tags: - events operationId: GetEventMutationOperation summary: Retrieve the status of a mutation involving banner ingestion parameters: - $ref: '#/components/parameters/MapSlug' - name: operationId in: path required: true schema: type: string format: uuid security: - ApiKeyAuth: [] responses: '200': description: Operation status. The `error` returned on failure contains no input URLs or internal keys. content: application/json: schema: $ref: '#/components/schemas/EventOperation' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/WriteForbidden' '404': description: The operation does not exist in the same map. '429': $ref: '#/components/responses/RateLimited' '/api/public/maps/{slug}/assets/{assetId}': get: tags: - assets operationId: GetAsset summary: Stable URL for an image asset description: | **302 redirects** to the image asset itself (signed URLs are short-lived, so access goes through this stable URL). v2 returns URLs in this form for `banners[].url` / `images[].image.url`, so you normally do not need to call it directly (a saved URL can be displayed or re-fetched as-is). No authentication is required, but only assets of **published maps** are resolved (404 for unpublished or nonexistent). parameters: - name: slug in: path required: true schema: type: string - name: assetId in: path required: true description: Asset ID (GUID). schema: type: string format: uuid security: [] responses: '302': description: Redirect to the permanent URL on the public CDN. headers: Location: schema: type: string description: Permanent URL on the public CDN. Cache-Control: schema: type: string example: 'public, max-age=60' '404': description: 'The map is unpublished or nonexistent, or the asset was not found.' components: securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-Api-Key description: Per-map API key (`pmk_` prefix). Issue and reissue it under **Advanced settings -> Integration API key** in the admin console. StaffTokenAuth: type: apiKey in: header name: X-Api-Key description: A scope-restricted token (`sst_` prefix) usable only on the spot operational status endpoints. parameters: MapSlug: name: slug in: path required: true description: 'The map''s public slug (the same slug as in the public URL `/d/{slug}`).' schema: type: string example: demo-mall MapSpotId: name: mapSpotId in: path required: true description: The spot's immutable public ID. Newly issued IDs are 8 characters with no prefix; already-issued IDs carrying the `spot_` prefix remain valid as stored. schema: type: string example: 6Y6SSBY5 IconKey: name: iconKey in: path required: true description: Stable key of a user image or a read-only preset image. schema: type: string EventId: name: eventId in: path required: true description: 'Event ID. The same value as `events[].id` in the public timetable `mapapp.timetable.v1`.' schema: type: string format: uuid IfMatch: name: If-Match in: header required: true description: The opaque ETag obtained from a GET response. Do not reconstruct it from the body. schema: type: string IdempotencyKey: name: Idempotency-Key in: header required: true description: '1-100 characters. The same result is returned for 24 hours for the same map, endpoint, and body.' schema: type: string minLength: 1 maxLength: 100 headers: RetryAfter: description: Seconds to wait before retrying. For the post-authentication limits, the time until the current one-minute window ends; for the pre-authentication abuse cap, the full window length (60). schema: type: integer minimum: 1 maximum: 60 responses: Unauthorized: description: | Authentication failed (invalid or unissued key, nonexistent `slug`, archived, or disabled tenant). The reason is not distinguished, in order to conceal existence. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: unauthorized ReadForbidden: description: The API key does not have Read permission. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: forbidden WriteForbidden: description: The API key does not have Write permission. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: forbidden DeleteForbidden: description: The API key does not have Delete permission. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: forbidden SpotNotFound: description: 'No spot was found for the specified `mapSpotId` or `subId`, or it is out of scope.' content: application/json: schema: $ref: '#/components/schemas/Error' example: error: spot_not_found EventValidationError: description: | Invalid date/time, title, body, color, related spots, or limit. Business errors of the event management API are returned with the same `{code, message}` as the admin console (only the existence-concealing 401 / 403 / 429 use `{error}`). content: application/json: schema: $ref: '#/components/schemas/ApiError' EventConflict: description: 'ETag conflict, idempotency key reuse, or the limit of 500 events per map has been reached.' content: application/json: schema: $ref: '#/components/schemas/ApiError' EventNotFound: description: No event with the specified `eventId` was found in the same map. content: application/json: schema: $ref: '#/components/schemas/ApiError' example: code: map_event_not_found message: イベントが見つかりません。 ImageNotFound: description: The specified image master was not found. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: image_not_found ValidationError: description: 'Invalid JSON shape, field, reference target, or limit.' content: application/json: schema: $ref: '#/components/schemas/Error' Conflict: description: 'A conflict in ETag, uniqueness, in-use confirmation, or idempotency.' content: application/json: schema: $ref: '#/components/schemas/Error' PreconditionRequired: description: '`If-Match` is required.' content: application/json: schema: $ref: '#/components/schemas/ApiError' example: code: precondition_required message: If-Matchヘッダが必要です。 ImageRejected: description: 'Failed to fetch the external image, or failed actual-format, decode, dimension, or format validation.' content: application/json: schema: $ref: '#/components/schemas/ApiError' ImageUnavailable: description: A temporary failure in image storage or in the external image source. content: application/json: schema: $ref: '#/components/schemas/ApiError' RateLimited: description: The rate limit for this endpoint has been exceeded. headers: Retry-After: $ref: '#/components/headers/RetryAfter' content: application/json: schema: $ref: '#/components/schemas/Error' OperationAccepted: description: A mutation involving a remote image was accepted. content: application/json: schema: type: object required: - operationId - status properties: operationId: type: string format: uuid status: type: string enum: - pending - running - succeeded schemas: V2Capabilities: type: object required: - schemaVersion - permissions - features - limits - endpoints properties: schemaVersion: type: string const: metamap.poi-management.v2 permissions: type: object required: - read - write - delete properties: read: type: boolean write: type: boolean delete: type: boolean features: $ref: '#/components/schemas/V2FeatureFlags' limits: type: object required: - pageSize - title - titleReading - bannersPerSpot - imageLongEdge - imagePixels properties: pageSize: type: integer const: 150 title: type: integer const: 1000 titleReading: type: integer const: 1000 bannersPerSpot: type: integer const: 15 imageLongEdge: type: integer const: 8192 imagePixels: type: integer const: 16777216 endpoints: type: object additionalProperties: type: string V2FeatureFlags: type: object required: - useSpotSubId - useBoothNumber - sponsorAdsEnabled - spotSectionsEnabled - congestionEnabled properties: useSpotSubId: type: boolean useBoothNumber: type: boolean sponsorAdsEnabled: type: boolean spotSectionsEnabled: type: boolean congestionEnabled: type: boolean V2References: type: object required: - schemaVersion - groups - floors - categories - displaySets - fields properties: schemaVersion: type: string const: metamap.poi-references.v2 groups: type: array items: $ref: '#/components/schemas/V2ReferenceItem' floors: type: array items: allOf: - $ref: '#/components/schemas/V2ReferenceItem' - type: object required: - groupId - label properties: groupId: type: string format: uuid label: type: string categories: type: array items: type: object required: - id - name - sortOrder properties: id: type: string format: uuid name: type: string sortOrder: type: integer displaySets: type: array items: allOf: - $ref: '#/components/schemas/V2ReferenceItem' - type: object required: - slug properties: slug: type: string fields: type: array items: type: object required: - id - key - label - type - enabled - publicVisible - isSystem - sortOrder properties: id: type: string format: uuid key: type: string label: type: string type: type: string enabled: type: boolean publicVisible: type: boolean isSystem: type: boolean systemKey: type: - string - 'null' sortOrder: type: integer V2ReferenceItem: type: object required: - id - name - enabled - sortOrder properties: id: type: string format: uuid name: type: string enabled: type: boolean sortOrder: type: integer V2ImageInput: type: object additionalProperties: false required: - url description: | `url` is a stable URL from a Metamaps response or a public HTTPS URL. Only PNG / JPEG / WebP are accepted, and images are optimized to WebP. The same Metamaps URL, `externalImageId`+`sourceRevision`, URL fingerprint+revision, or post-conversion SHA-256 results in a no-op or reuse. `externalImageId` and `sourceRevision` must be opaque values containing no secrets; the original URL is never stored in plaintext in the database, responses, audit records, or logs. properties: url: type: string format: uri externalImageId: type: - string - 'null' maxLength: 200 sourceRevision: type: - string - 'null' maxLength: 200 forceRefresh: type: boolean default: false V2SponsorAdInput: type: - object - 'null' additionalProperties: false properties: enabled: type: boolean image: oneOf: - $ref: '#/components/schemas/V2ImageInput' - type: 'null' V2SpotMutationFields: type: object additionalProperties: false properties: type: type: string enum: - poi - icon description: Specify on creation only. Use the convert endpoint to change the type of an existing spot. title: type: string maxLength: 1000 floorId: type: string format: uuid lat: type: number format: double minimum: -90 maximum: 90 lng: type: number format: double minimum: -180 maximum: 180 destinationFloorId: type: - string - 'null' format: uuid destinationLat: type: - number - 'null' format: double minimum: -90 maximum: 90 destinationLng: type: - number - 'null' format: double minimum: -180 maximum: 180 subId: type: - string - 'null' maxLength: 100 titleReading: type: - string - 'null' maxLength: 1000 boothNumber: type: - string - 'null' maxLength: 50 iconKey: type: - string - 'null' logoIconKey: type: - string - 'null' banners: type: - array - 'null' maxItems: 15 items: $ref: '#/components/schemas/V2ImageInput' description: type: - string - 'null' maxLength: 2000 contact: type: - object - 'null' description: Specify valid standard fields from `/references.fields` by systemKey. Pictograms accept website only. additionalProperties: true hours: oneOf: - $ref: '#/components/schemas/V2SpotHours' - type: 'null' description: | Business hours by day of the week, closing days, and notes. POI only; a pictogram returns `400 field_not_supported_for_spot_type`. The values you send are saved exactly as sent; Metamaps does not generate or change them with AI. The whole object is replaced: omitting it keeps the current value, and null clears all three items. An unknown key, an unknown day, or a value over the length limit returns `400 invalid_hours`. The free-text business hours entered in the admin console are not part of this API; they are neither returned nor changed by this API. customFields: type: - object - 'null' description: A full-replacement object specifying valid user fields from `/references.fields` by key. additionalProperties: true spotSections: type: - array - 'null' maxItems: 50 description: | Spot custom fields. A set of fields with headings that has no map-level field definition and is self-contained within this spot. The entire array is replaced, and **the array order is exactly the display order on the public page**. null clears everything; omitting it keeps the current value. If the map's `spotSectionsEnabled` is OFF, it is not saved and is reported via `ignoredFields`. items: $ref: '#/components/schemas/V2SpotSection' isVisible: type: boolean categoryIds: type: - array - 'null' maxItems: 50 uniqueItems: true items: type: string format: uuid isIncludedInDefault: type: boolean displaySetIds: type: - array - 'null' maxItems: 100 uniqueItems: true items: type: string format: uuid groupIds: type: - array - 'null' maxItems: 100 uniqueItems: true items: type: string format: uuid displayPriority: type: integer minimum: 0 maximum: 9999 poiDisplayMode: type: - string - 'null' enum: - marker - label - null iconDisplayPriority: type: - string - 'null' enum: - low - standard - high - null iconPriorityOverPoi: type: boolean iconAlwaysVisible: type: boolean iconRouteGuideEnabled: type: boolean sponsorAd: $ref: '#/components/schemas/V2SponsorAdInput' V2SpotCreateRequest: allOf: - $ref: '#/components/schemas/V2SpotMutationFields' - type: object required: - type - title - floorId - lat - lng V2SpotPatchRequest: allOf: - $ref: '#/components/schemas/V2SpotMutationFields' - type: object properties: type: false V2SpotHours: type: object additionalProperties: false description: Business hours. Only the three keys below are accepted. properties: regular: type: array description: Business hours by day of the week. Put days that share the same hours in one row. items: $ref: '#/components/schemas/V2SpotHoursRow' closed: type: array description: Closing days as free text. items: type: string maxLength: 100 note: type: - string - 'null' maxLength: 500 description: Additional notes on the business hours. example: regular: - days: - mon - tue - wed - thu - fri open: '11:00' close: '22:00' lastOrder: '21:30' - days: - sat - sun - holiday open: '10:00' close: '21:00' lastOrder: null closed: - 2nd Tuesday of each month - New Year holidays note: Hours may change on the day before a public holiday. V2SpotHoursRow: type: object additionalProperties: false required: - days - open - close properties: days: type: array description: Days this row applies to. `holiday` means public holidays. items: type: string enum: - mon - tue - wed - thu - fri - sat - sun - holiday open: type: string maxLength: 20 description: 'Opening time in 24-hour `HH:MM`, such as `09:00`.' close: type: string maxLength: 20 description: 'Closing time in 24-hour `HH:MM`.' lastOrder: type: - string - 'null' maxLength: 20 description: 'Last order time in 24-hour `HH:MM`. null or omitted if there is none.' V2SpotSection: type: object required: - items properties: title: type: - string - 'null' maxLength: 50 description: 'Heading. If unset or empty, no heading row is shown on the public page.' items: type: array minItems: 1 maxItems: 30 description: Label-and-value rows. Rows with an empty label or value are not published. items: type: object required: - label - value properties: label: type: string minLength: 1 maxLength: 50 value: type: string minLength: 1 maxLength: 2000 description: | If the value contains a URL, it automatically becomes a link on the public page. When the entire value is a single URL, only the domain is shown and the full URL appears in a tooltip. V2Asset: type: object readOnly: true required: - assetId - url - thumbnailUrl - width - height - sizeBytes - sha256 properties: assetId: type: - string - 'null' format: uuid description: ID of a map-owned asset. null for presets shared across all maps. url: type: string format: uri thumbnailUrl: type: - string - 'null' format: uri width: type: - integer - 'null' height: type: - integer - 'null' sizeBytes: type: integer format: int64 sha256: type: - string - 'null' pattern: '^[0-9a-f]{64}$' description: WebP SHA-256 of a map-owned asset. null for presets shared across all maps. V2IgnoredField: type: object required: - path - reason - feature properties: path: type: string reason: type: string const: feature_disabled feature: type: string V2ImageResult: type: object required: - path - result properties: path: type: string result: type: string enum: - unchanged - reused - created - replaced - removed V2Spot: type: object readOnly: true required: - mapSpotId - type - title - subId - titleReading - titleReadingEngine - titleReadingNeedsReview - boothNumber - floorId - lat - lng - destinationFloorId - destinationLat - destinationLng - iconKey - logoIconKey - banners - description - contact - hours - customFields - spotSections - isVisible - categoryIds - isIncludedInDefault - displaySetIds - groupIds - linkedMapSpotIds - displayPriority - poiDisplayMode - iconDisplayPriority - iconPriorityOverPoi - iconAlwaysVisible - iconRouteGuideEnabled - sponsorAd - features - eTag - createdAt - updatedAt - changed properties: mapSpotId: type: string type: type: string enum: - poi - icon title: type: string maxLength: 1000 subId: type: - string - 'null' titleReading: type: - string - 'null' maxLength: 1000 titleReadingEngine: type: - string - 'null' titleReadingNeedsReview: type: boolean boothNumber: type: - string - 'null' floorId: type: string format: uuid lat: type: number format: double lng: type: number format: double destinationFloorId: type: - string - 'null' format: uuid destinationLat: type: - number - 'null' format: double destinationLng: type: - number - 'null' format: double iconKey: type: - string - 'null' logoIconKey: type: - string - 'null' banners: type: array items: $ref: '#/components/schemas/V2Asset' description: type: - string - 'null' contact: type: - object - 'null' additionalProperties: true hours: oneOf: - $ref: '#/components/schemas/V2SpotHours' - type: 'null' customFields: type: - object - 'null' additionalProperties: true spotSections: type: - array - 'null' maxItems: 50 items: $ref: '#/components/schemas/V2SpotSection' isVisible: type: boolean categoryIds: type: array items: type: string format: uuid isIncludedInDefault: type: boolean displaySetIds: type: array items: type: string format: uuid groupIds: type: array items: type: string format: uuid linkedMapSpotIds: type: array items: type: string displayPriority: type: integer poiDisplayMode: type: - string - 'null' enum: - marker - label - null iconDisplayPriority: type: string enum: - low - standard - high iconPriorityOverPoi: type: boolean iconAlwaysVisible: type: boolean iconRouteGuideEnabled: type: boolean sponsorAd: type: - object - 'null' properties: enabled: type: boolean image: oneOf: - $ref: '#/components/schemas/V2Asset' - type: 'null' features: $ref: '#/components/schemas/V2FeatureFlags' eTag: type: string description: An opaque aggregate ETag. createdAt: type: string format: date-time updatedAt: type: string format: date-time changed: type: boolean ignoredFields: type: - array - 'null' items: $ref: '#/components/schemas/V2IgnoredField' imageResults: type: - array - 'null' items: $ref: '#/components/schemas/V2ImageResult' V2SpotPage: type: object required: - schemaVersion - items - page - pageSize - total properties: schemaVersion: type: string const: metamap.poi-management.v2 items: type: array items: $ref: '#/components/schemas/V2Spot' page: type: integer minimum: 1 pageSize: type: integer minimum: 1 maximum: 150 total: type: integer minimum: 0 V2SpotDeleteResult: type: object required: - deletedMapSpotIds properties: deletedMapSpotIds: type: array minItems: 1 items: type: string V2ImageMutationFields: type: object additionalProperties: false properties: name: type: string maxLength: 50 image: $ref: '#/components/schemas/V2ImageInput' classifications: type: - array - 'null' uniqueItems: true items: type: string enum: - pictogram - spotLogo - category enabled: type: boolean forceSquare: type: boolean displayLongEdgeM: type: number format: double sortOrder: type: integer minimum: 0 V2ImageCreateRequest: allOf: - $ref: '#/components/schemas/V2ImageMutationFields' - type: object required: - name - image V2ImagePatchRequest: $ref: '#/components/schemas/V2ImageMutationFields' V2Image: type: object readOnly: true required: - iconKey - name - classifications - enabled - forceSquare - displayLongEdgeM - sortOrder - readOnly - usageCount - image - eTag - createdAt - updatedAt - changed properties: iconKey: type: string name: type: string classifications: type: array items: type: string enum: - pictogram - spotLogo - category enabled: type: boolean forceSquare: type: boolean displayLongEdgeM: type: number format: double sortOrder: type: integer readOnly: type: boolean usageCount: type: integer minimum: 0 image: $ref: '#/components/schemas/V2Asset' eTag: type: - string - 'null' createdAt: type: string format: date-time updatedAt: type: string format: date-time changed: type: boolean imageResults: type: - array - 'null' items: $ref: '#/components/schemas/V2ImageResult' V2ImageList: type: object required: - schemaVersion - items properties: schemaVersion: type: string const: metamap.poi-images.v2 items: type: array items: $ref: '#/components/schemas/V2Image' V2Operation: type: object required: - operationId - status - resourceType - resourceKey - result - error - createdAt - updatedAt - completedAt properties: operationId: type: string format: uuid status: type: string enum: - pending - running - succeeded - failed - cancelled resourceType: type: string enum: - spot - image resourceKey: type: - string - 'null' result: type: - object - 'null' additionalProperties: true error: type: - string - 'null' createdAt: type: string format: date-time updatedAt: type: string format: date-time completedAt: type: - string - 'null' format: date-time SpotStatusMutation: type: object additionalProperties: false required: - config properties: config: type: string description: StableKey or alias of the status set. definition: type: - string - 'null' description: StableKey or alias of the status definition. values: type: - object - 'null' additionalProperties: true isEnabled: type: - boolean - 'null' SpotStatusSingleRequest: type: object additionalProperties: false required: - statuses properties: statuses: type: array maxItems: 5 items: $ref: '#/components/schemas/SpotStatusMutation' SpotStatusBatchRequest: type: object additionalProperties: false required: - updates properties: updates: type: array maxItems: 2000 items: type: object additionalProperties: false required: - mapSpotId - statuses properties: mapSpotId: type: string statuses: type: array maxItems: 5 items: $ref: '#/components/schemas/SpotStatusMutation' SpotStatusResponse: type: object required: - schemaVersion - configs - spots properties: schemaVersion: type: string const: metamap.spot-status.v1 configs: type: array items: type: object required: - stableKey - alias - name - validMinutes - isEnabled - definitions properties: stableKey: type: string alias: type: - string - 'null' name: type: string validMinutes: type: integer minimum: 0 isEnabled: type: boolean definitions: type: array items: type: object required: - stableKey - alias - label - valueSchema - displayCondition - sortOrder properties: stableKey: type: string alias: type: - string - 'null' label: type: string valueSchema: type: - array - 'null' displayCondition: type: integer sortOrder: type: integer spots: type: array items: type: object required: - mapSpotId - statuses properties: mapSpotId: type: string statuses: type: array items: type: object required: - config - definition - values - isEnabled - valueUpdatedAt properties: config: type: string definition: type: string values: type: - object - 'null' additionalProperties: true isEnabled: type: boolean valueUpdatedAt: type: string format: date-time ignoredFields: type: - array - 'null' items: $ref: '#/components/schemas/V2IgnoredField' CongestionValue: type: object required: - mapSpotId - definitionKey - state - value - confirmedAt - expiresAt - updatedAt properties: mapSpotId: type: string description: Spot StableKey within the map. An opaque string matched exactly. example: 6Y6SSBY5 definitionKey: type: string description: StableKey of the congestion definition assigned in the admin console. example: 9M5Q2X7R state: type: string enum: - observed - default - hidden value: type: - integer - 'null' minimum: 0 maximum: 32767 confirmedAt: type: - string - 'null' format: date-time expiresAt: type: - string - 'null' format: date-time updatedAt: type: - string - 'null' format: date-time CongestionDefinitionOption: type: object additionalProperties: false required: - value - label properties: value: type: integer minimum: 0 maximum: 9 label: type: string CongestionDefinition: type: object additionalProperties: false required: - definitionKey - name - type - unit - validMinutes - expiredBehavior - defaultValue - minimumValue - maximumValue - options - template properties: definitionKey: type: string description: An immutable StableKey configured in the admin console. name: type: string description: Name for administrative use. type: type: string enum: - indicator - level - number unit: type: - string - 'null' enum: - minute - null validMinutes: type: - integer - 'null' minimum: 1 maximum: 10080 description: How long an observed value stays valid. null means no expiry; `expiresAt` is then null even when state=observed. expiredBehavior: type: string enum: - hide - default defaultValue: type: - integer - 'null' minimum: 0 maximum: 32767 minimumValue: type: integer minimum: 0 maximum: 32767 maximumValue: type: integer minimum: 0 maximum: 32767 options: type: array description: Permitted values for indicator / level and their wording in the default language. An empty array for number. items: $ref: '#/components/schemas/CongestionDefinitionOption' template: type: - string - 'null' description: 'Default-language template for number. Contains exactly one `{value}`.' CongestionValuesResponse: type: object required: - schemaVersion - generatedAt - definitions - items properties: schemaVersion: type: string const: metamap.congestion-values.v2 generatedAt: type: string format: date-time definitions: type: array items: $ref: '#/components/schemas/CongestionDefinition' items: type: array items: $ref: '#/components/schemas/CongestionValue' CongestionValueResponse: type: object additionalProperties: false required: - schemaVersion - generatedAt - definition - item properties: schemaVersion: type: string const: metamap.congestion-values.v2 generatedAt: type: string format: date-time definition: $ref: '#/components/schemas/CongestionDefinition' item: $ref: '#/components/schemas/CongestionValue' CongestionBatchUpdateRequest: type: object additionalProperties: false required: - updates properties: updates: type: array minItems: 1 maxItems: 2000 items: type: object additionalProperties: false required: - mapSpotId - expectedDefinitionKey - value properties: mapSpotId: type: string minLength: 1 expectedDefinitionKey: type: string minLength: 1 description: Identifies one assigned status and confirms its definition key. The assignment itself is not changed. value: type: - integer - 'null' minimum: 0 maximum: 32767 CongestionSingleUpdateRequest: type: object additionalProperties: false required: - expectedDefinitionKey - value properties: expectedDefinitionKey: type: string minLength: 1 description: Identifies one assigned status and confirms its definition key. The assignment itself is not changed. value: type: - integer - 'null' minimum: 0 maximum: 32767 CongestionBatchUpdateResponse: allOf: - $ref: '#/components/schemas/CongestionValuesResponse' - type: object required: - affectedMapSpotIds properties: affectedMapSpotIds: type: array uniqueItems: true items: type: string CongestionSingleUpdateResponse: allOf: - $ref: '#/components/schemas/CongestionValueResponse' - type: object required: - affectedMapSpotIds properties: affectedMapSpotIds: type: array uniqueItems: true items: type: string EventCapabilities: type: object required: - schemaVersion - permissions - settings - limits - endpoints properties: schemaVersion: type: string const: metamap.event-management.v1 permissions: type: object required: - read - write - delete properties: read: type: boolean write: type: boolean delete: type: boolean settings: $ref: '#/components/schemas/EventSettings' limits: type: object required: - events - spotsPerEvent - title - text - pageSize properties: events: type: integer const: 500 spotsPerEvent: type: integer const: 20 title: type: integer const: 1000 text: type: integer const: 2000 pageSize: type: integer const: 150 endpoints: type: object additionalProperties: type: string EventSettings: type: object required: - eventsEnabled - eventsVisibleFrom - eventsVisibleTo - eTag properties: eventsEnabled: type: boolean description: Whether to show "Events" in the public menu. Events and images are retained even when OFF. eventsVisibleFrom: type: - string - 'null' format: date-time description: Publication start (UTC). `null` means unlimited. eventsVisibleTo: type: - string - 'null' format: date-time description: Publication end (UTC). `null` means unlimited. eTag: type: string description: An ETag derived from these three fields only. It does not change when other map settings change. EventSettingsPatchRequest: type: object additionalProperties: false properties: eventsEnabled: type: boolean eventsVisibleFrom: type: - string - 'null' format: date-time eventsVisibleTo: type: - string - 'null' format: date-time EventSpotRef: type: object additionalProperties: false required: - type - mapSpotId properties: type: type: string enum: - poi - areaMap description: | `poi` is a spot and `areaMap` is a detailed area map spot. Pictograms and simple area map spots cannot be linked, because they have no detail card on the public side. mapSpotId: type: string description: | The `mapSpotId` from POI management API v2 (the spot's immutable public ID). For `poi`, any ID among the linked siblings points to the same logical spot, and the response returns one representative of that logical spot. example: 6Y6SSBY5 EventBannerInput: type: object additionalProperties: false required: - url properties: url: type: string format: uri description: | An external HTTPS URL. PNG / JPEG / WebP are validated by actual format, the banner limits are applied, and the image is stored as WebP. The original URL is not retained in storage, responses, or logs. externalImageId: type: - string - 'null' maxLength: 200 description: The image ID on the external system. Do not include secret values. sourceRevision: type: - string - 'null' maxLength: 200 description: | The image revision. For a resend to the same event where the normalized URL, `externalImageId`, and `sourceRevision` all match, no fetch is performed at all. Even when the fetched result is the same image as the current banner, it is not replaced and the event is returned with 200. forceRefresh: type: boolean default: false description: 'Ignores the decision to skip fetching and fetches again (if the content is identical, no replacement occurs).' Event: type: object required: - eventId - isEnabled - startsAt - endsAt - title - useRichText - color - borderEnabled - borderColor - spots - eTag - createdAt - updatedAt properties: eventId: type: string format: uuid description: 'The same value as `events[].id` in the public timetable `mapapp.timetable.v1`.' isEnabled: type: boolean description: Whether to include it as a publication candidate. Events set to false are not published even within the publication period. startsAt: type: string format: date-time endsAt: type: string format: date-time title: type: string minLength: 1 maxLength: 1000 text: type: - string - 'null' maxLength: 2000 useRichText: type: boolean description: Whether the admin console rich body is in use. Read-only. bannerImageUrl: type: - string - 'null' description: Stable URL of the dedicated banner. Read-only. color: type: string pattern: '^#[0-9a-f]{6}$' borderEnabled: type: boolean borderColor: type: string pattern: '^#[0-9a-f]{6}$' spots: type: array maxItems: 20 description: 'Related spots, in the display order used on the public side. Rows whose reference target has been deleted are not included.' items: $ref: '#/components/schemas/EventSpotRef' eTag: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time EventPage: type: object required: - schemaVersion - items - page - pageSize - total properties: schemaVersion: type: string const: metamap.event-management.v1 items: type: array items: $ref: '#/components/schemas/Event' page: type: integer minimum: 1 pageSize: type: integer minimum: 1 maximum: 150 total: type: integer minimum: 0 EventCreateRequest: type: object additionalProperties: false required: - startsAt - endsAt - title properties: isEnabled: type: boolean default: true startsAt: type: string format: date-time description: Start (UTC). Seconds and milliseconds are rounded down to 0. endsAt: type: string format: date-time description: | End (UTC). Must fall on the same JST date as the start, or be exactly 0:00 the next day (24:00 of the same day). The duration must be at least 1 minute and at most 24 hours. title: type: string minLength: 1 maxLength: 1000 text: type: - string - 'null' maxLength: 2000 banner: oneOf: - $ref: '#/components/schemas/EventBannerInput' - type: 'null' color: type: string pattern: '^#[0-9a-f]{6}$' default: '#ffffff' borderEnabled: type: boolean default: false borderColor: type: string pattern: '^#[0-9a-f]{6}$' default: '#e5e7eb' spots: type: array maxItems: 20 items: $ref: '#/components/schemas/EventSpotRef' EventPatchRequest: type: object additionalProperties: false description: 'Omitted fields keep their current values, `null` clears them, and arrays are fully replaced.' properties: isEnabled: type: boolean startsAt: type: string format: date-time endsAt: type: string format: date-time title: type: string minLength: 1 maxLength: 1000 text: type: - string - 'null' maxLength: 2000 banner: oneOf: - $ref: '#/components/schemas/EventBannerInput' - type: 'null' color: type: string pattern: '^#[0-9a-f]{6}$' borderEnabled: type: boolean borderColor: type: string pattern: '^#[0-9a-f]{6}$' spots: type: array maxItems: 20 items: $ref: '#/components/schemas/EventSpotRef' EventOperation: type: object required: - operationId - status - resourceType - resourceKey - result - error - createdAt - updatedAt - completedAt properties: operationId: type: string format: uuid status: type: string enum: - pending - running - succeeded - failed - cancelled resourceType: type: string const: mapEvent resourceKey: type: - string - 'null' description: The target `eventId`. On creation it is null until the operation completes. result: oneOf: - $ref: '#/components/schemas/Event' - type: 'null' error: type: - string - 'null' createdAt: type: string format: date-time updatedAt: type: string format: date-time completedAt: type: - string - 'null' format: date-time Error: type: object required: - error properties: error: type: string example: unauthorized ApiError: type: object additionalProperties: false required: - code - message properties: code: type: string example: image_fetch_timeout message: type: string examples: CongestionValuesExample: summary: Example response for retrieving current congestion values value: schemaVersion: metamap.congestion-values.v2 generatedAt: '2026-08-15T03:00:00Z' definitions: - definitionKey: 9M5Q2X7R name: 3段階(空いている・普通・混雑) type: level unit: null validMinutes: 30 expiredBehavior: hide defaultValue: null minimumValue: 0 maximumValue: 2 options: - value: 0 label: 空いている - value: 1 label: 普通 - value: 2 label: 混雑 template: null items: - mapSpotId: 6Y6SSBY5 definitionKey: 9M5Q2X7R state: observed value: 2 confirmedAt: '2026-08-15T02:58:00Z' expiresAt: '2026-08-15T03:28:00Z' updatedAt: '2026-08-15T02:58:00Z' - mapSpotId: 7A7TTCA6 definitionKey: 9M5Q2X7R state: hidden value: null confirmedAt: null expiresAt: null updatedAt: '2026-08-15T02:50:00Z' CongestionUpdateExample: summary: Example of a bulk update of current congestion values value: updates: - mapSpotId: 6Y6SSBY5 expectedDefinitionKey: 9M5Q2X7R value: 2 - mapSpotId: 7A7TTCA6 expectedDefinitionKey: 9M5Q2X7R value: null