{
  "openapi": "3.1.0",
  "info": {
    "title": "Gridex Customer Portal API",
    "version": "2026-10-12.1",
    "description": "Production API for customer portals. Access is organization-scoped by the server-side API credential and customer data is limited to the verified linked customer identity."
  },
  "servers": [
    {
      "url": "https://app.gridex.se"
    }
  ],
  "paths": {
    "/api/v1/customer-portal/sync": {
      "post": {
        "operationId": "postApiV1CustomerPortalSync",
        "summary": "Link or verify an external customer portal identity",
        "security": [
          {
            "bearerAuth": [
              "customer_sync.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_sync.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "external_customer_id",
                  "customer_portal_user_id",
                  "auth_user_id"
                ],
                "properties": {
                  "external_customer_id": {
                    "type": "string"
                  },
                  "external_account_id": {
                    "type": "string"
                  },
                  "customer_portal_user_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
                  },
                  "auth_user_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "personal_number": {
                    "type": "string"
                  },
                  "organization_number": {
                    "type": "string"
                  },
                  "customer_number": {
                    "type": "string"
                  },
                  "facility_id": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                },
                "dependentRequired": {
                  "auth_user_id": [
                    "customer_portal_user_id"
                  ],
                  "customer_portal_user_id": [
                    "auth_user_id"
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tenant- och kundfiltrerad portalsynk med profil, anläggningar, avtal, fakturor, mätvärden, juridik, händelser, dokument, fullmakter och notiser.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PortalSyncData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Link or verify an external customer portal identity.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/contracts": {
      "get": {
        "operationId": "getApiV1CustomerContracts",
        "summary": "Retrieve the customer’s electricity contracts",
        "security": [
          {
            "bearerAuth": [
              "customer_contracts.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_contracts.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerContract"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the customer’s electricity contracts.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/documents": {
      "get": {
        "operationId": "getApiV1CustomerDocuments",
        "summary": "Retrieve customer documents without exposing internal storage paths",
        "security": [
          {
            "bearerAuth": [
              "customer_documents.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_documents.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve customer documents without exposing internal storage paths.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/events": {
      "get": {
        "operationId": "getApiV1CustomerEvents",
        "summary": "Retrieve customer-visible events",
        "security": [
          {
            "bearerAuth": [
              "customer_events.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_events.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve customer-visible events.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/invoices": {
      "get": {
        "operationId": "getApiV1CustomerInvoices",
        "summary": "Retrieve the customer’s invoices",
        "security": [
          {
            "bearerAuth": [
              "customer_invoices.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_invoices.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the customer’s invoices.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/invoices/{id}": {
      "get": {
        "operationId": "getApiV1CustomerInvoicesId",
        "summary": "Retrieve a single customer invoice",
        "security": [
          {
            "bearerAuth": [
              "customer_invoices.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_invoices.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve a single customer invoice.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/legal-acceptances": {
      "get": {
        "operationId": "getApiV1CustomerLegalAcceptances",
        "summary": "Retrieve the customer’s recorded legal acceptances",
        "security": [
          {
            "bearerAuth": [
              "customer_legal.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_legal.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the customer’s recorded legal acceptances.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/me": {
      "get": {
        "operationId": "getApiV1CustomerMe",
        "summary": "Retrieve the linked customer profile",
        "security": [
          {
            "bearerAuth": [
              "customer_profile.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_profile.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the linked customer profile.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/metering-values": {
      "get": {
        "operationId": "getApiV1CustomerMeteringValues",
        "summary": "Retrieve metering values available to the customer",
        "security": [
          {
            "bearerAuth": [
              "customer_metering.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_metering.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve metering values available to the customer. The list is a bounded detail list of current interval values; it is not a complete-month aggregate. Do not sum it to show monthly totals: a month can contain more values than one response returns.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "expensive",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/move-out": {
      "post": {
        "operationId": "postApiV1CustomerMoveOut",
        "summary": "Submit a customer move-out request",
        "security": [
          {
            "bearerAuth": [
              "customer_facility_data.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_facility_data.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerMoveOutRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerMoveOutData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "201": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerMoveOutData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Submit a customer move-out request.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/notifications": {
      "get": {
        "operationId": "getApiV1CustomerNotifications",
        "summary": "Retrieve customer notifications",
        "security": [
          {
            "bearerAuth": [
              "customer_notifications.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_notifications.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve customer notifications.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/notifications/read": {
      "post": {
        "operationId": "postApiV1CustomerNotificationsRead",
        "summary": "Mark customer notifications as read",
        "security": [
          {
            "bearerAuth": [
              "customer_notifications.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_notifications.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerNotificationReadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerNotificationReadData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Mark customer notifications as read.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/portal-bundle": {
      "get": {
        "operationId": "getApiV1CustomerPortalBundle",
        "summary": "Retrieve the combined customer portal read model for a verified customer identity",
        "security": [
          {
            "bearerAuth": [
              "customer_profile.read",
              "customer_sites.read",
              "customer_contracts.read",
              "customer_invoices.read",
              "customer_metering.read",
              "customer_legal.read",
              "customer_events.read",
              "customer_documents.read",
              "customer_notifications.read",
              "customer_power_of_attorney.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_profile.read",
          "customer_sites.read",
          "customer_contracts.read",
          "customer_invoices.read",
          "customer_metering.read",
          "customer_legal.read",
          "customer_events.read",
          "customer_documents.read",
          "customer_notifications.read",
          "customer_power_of_attorney.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the combined customer portal read model for a verified customer identity.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      },
      "post": {
        "operationId": "postApiV1CustomerPortalBundle",
        "summary": "Retrieve the combined customer portal read model for a verified customer identity",
        "security": [
          {
            "bearerAuth": [
              "customer_profile.read",
              "customer_sites.read",
              "customer_contracts.read",
              "customer_invoices.read",
              "customer_metering.read",
              "customer_legal.read",
              "customer_events.read",
              "customer_documents.read",
              "customer_notifications.read",
              "customer_power_of_attorney.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_profile.read",
          "customer_sites.read",
          "customer_contracts.read",
          "customer_invoices.read",
          "customer_metering.read",
          "customer_legal.read",
          "customer_events.read",
          "customer_documents.read",
          "customer_notifications.read",
          "customer_power_of_attorney.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClosedPortalMutationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the combined customer portal read model for a verified customer identity.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/powers-of-attorney": {
      "get": {
        "operationId": "getApiV1CustomerPowersOfAttorney",
        "summary": "Retrieve the customer’s powers of attorney",
        "security": [
          {
            "bearerAuth": [
              "customer_power_of_attorney.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_power_of_attorney.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the customer’s powers of attorney.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/profile-update": {
      "post": {
        "operationId": "postApiV1CustomerProfileUpdate",
        "summary": "Submit a customer contact or site-address update",
        "security": [
          {
            "bearerAuth": [
              "customer_contact.write"
            ]
          },
          {
            "bearerAuth": [
              "customer_facility_data.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_contact.write",
          "customer_facility_data.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerProfileUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerProfileUpdateData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "x-scope-mode": "any-per-request; both required when both operations are present",
        "x-scope-requirement": {
          "anyOf": [
            "customer_contact.write",
            "customer_facility_data.write"
          ],
          "allOfWhenBothPayloadSectionsArePresent": [
            "customer_contact.write",
            "customer_facility_data.write"
          ]
        },
        "description": "Submit a customer contact or site-address update.",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/sites": {
      "get": {
        "operationId": "getApiV1CustomerSites",
        "summary": "Retrieve the customer’s electricity sites",
        "security": [
          {
            "bearerAuth": [
              "customer_sites.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_sites.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClosedPortalResourceEnvelope"
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve the customer’s electricity sites.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/sync": {
      "post": {
        "operationId": "postApiV1CustomerSync",
        "summary": "Submit customer data required to complete an existing customer record or process",
        "security": [
          {
            "bearerAuth": [
              "customer_sync.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_sync.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerSyncRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerSyncData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Submit customer data required to complete an existing customer record or process.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/events": {
      "get": {
        "operationId": "getApiV1Events",
        "summary": "Retrieve domain events available to the authenticated organization",
        "security": [
          {
            "bearerAuth": [
              "events.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "events.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^customer\\.[a-z0-9_]+$"
            }
          },
          {
            "name": "external_customer_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "next_before",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DomainEventListData"
                    },
                    "next_before": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Retrieve domain events available to the authenticated organization.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      },
      "post": {
        "operationId": "postApiV1Events",
        "summary": "Submit a customer-facing integration event",
        "security": [
          {
            "bearerAuth": [
              "website_events.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "website_events.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerEventRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerEventData"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Submit a customer-facing integration event.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/integration/context": {
      "get": {
        "tags": [
          "Integration context"
        ],
        "summary": "Verify the authenticated API client and retrieve its public integration context",
        "description": "Verify the authenticated API client and retrieve its public integration context.",
        "responses": {
          "200": {
            "description": "organization context",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/IntegrationContext"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/IntegrationContext"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "operationId": "getApiV1IntegrationContext",
        "x-required-scopes": [
          "integration_context.read"
        ],
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references",
        "security": [
          {
            "bearerAuth": [
              "integration_context.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ]
      }
    },
    "/api/v1/openapi/customer-portal-v1.json": {
      "get": {
        "summary": "Current OpenAPI specification for customer portal integrations",
        "description": "Current OpenAPI specification for customer portal integrations.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-12.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-12.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1OpenapiCustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "private-revalidate",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-02.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-02.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-02.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-02.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-02.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608021CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-03.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-03.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-03.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-03.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-03.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608031CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-04.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-04.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-04.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-04.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-04.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608041CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-04.3/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-04.3",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-04.3.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-04.3"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-04.3"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608043CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-04.2/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-04.2",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-04.2.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-04.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-04.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608042CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-05.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-05.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-05.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-05.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-05.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608051CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-05.2/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-05.2",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-05.2.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-05.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-05.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608052CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-10.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-10.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-10.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-10.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-10.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608101CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-14.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-14.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-14.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-14.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-14.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608141CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-19.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-19.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-19.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-19.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-19.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608191CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-19.2/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-19.2",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-19.2.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-19.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-19.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608192CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-20.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-20.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-20.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-20.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-20.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608201CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-20.2/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-20.2",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-20.2.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-20.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-20.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608202CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-08-22.2/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-08-22.2",
        "description": "Immutable Customer Portal OpenAPI release 2026-08-22.2.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-22.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-08-22.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202608222CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-01.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-01.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-01.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-01.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-01.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610011CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-02.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-02.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-02.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610021CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-02.2/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-02.2",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-02.2.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.2"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610022CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-02.3/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-02.3",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-02.3.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.3"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.3"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610023CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/customer/support/cases": {
      "get": {
        "operationId": "getApiV1CustomerSupportCases",
        "summary": "List the customer’s support cases",
        "security": [
          {
            "bearerAuth": [
              "customer_support.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Opaque cursor from page.next_cursor; bound to the customer and resource."
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version",
                    "page"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerSupportCase"
                      }
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    },
                    "page": {
                      "$ref": "#/components/schemas/PortalPage"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Lists support cases of the verified customer, newest first, filtered in the database before pagination. Requires an actively linked portal user. Internal notes, phone logs and technical case events are never returned.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      },
      "post": {
        "operationId": "postApiV1CustomerSupportCases",
        "summary": "Open a support case",
        "security": [
          {
            "bearerAuth": [
              "customer_support.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerSupportCaseCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerSupportCase"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Opens a support case with the customer’s first message. The same Idempotency-Key and payload replay the same case; a different payload is rejected with 409. Requires an actively linked portal user. Internal notes, phone logs and technical case events are never returned.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/support/cases/{reference}": {
      "get": {
        "operationId": "getApiV1CustomerSupportCasesReference",
        "summary": "Retrieve a support case with its customer-visible messages",
        "security": [
          {
            "bearerAuth": [
              "customer_support.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public case reference returned by this API. Lookups are always bounded to the verified customer."
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerSupportCaseDetail"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Next-Cursor": {
                "description": "Present only when another page exists. Send the value unchanged as the cursor query parameter to read the next page; absent on the last page.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Ärendet hittades inte för den verifierade kunden.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Requires an actively linked portal user. Internal notes, phone logs and technical case events are never returned. messages contains at most the first 500 customer-visible messages. When later messages exist the response carries X-Gridex-Next-Cursor; continue with GET .../messages?cursor=<value>.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/support/cases/{reference}/messages": {
      "get": {
        "operationId": "getApiV1CustomerSupportCasesReferenceMessages",
        "summary": "List customer-visible messages of a support case",
        "security": [
          {
            "bearerAuth": [
              "customer_support.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public case reference returned by this API. Lookups are always bounded to the verified customer."
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Opaque continuation value from X-Gridex-Next-Cursor of the previous response. Bound to the organization, the verified customer and the case; a modified or foreign cursor returns 400 invalid_cursor. Without cursor the first page is returned, identical to earlier V1 behaviour."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerSupportMessage"
                      }
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Next-Cursor": {
                "description": "Present only when another page exists. Send the value unchanged as the cursor query parameter to read the next page; absent on the last page.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering. invalid_cursor: the cursor was modified, expired or belongs to another case, customer or organization.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Ärendet hittades inte för den verifierade kunden.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Requires an actively linked portal user. Internal notes, phone logs and technical case events are never returned. Returns customer-visible messages oldest first, at most 500 per response. When more exist the response carries X-Gridex-Next-Cursor; repeat with ?cursor=<value> until the header is absent. The response body shape is unchanged.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      },
      "post": {
        "operationId": "postApiV1CustomerSupportCasesReferenceMessages",
        "summary": "Add a customer message to an open support case",
        "security": [
          {
            "bearerAuth": [
              "customer_support.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public case reference returned by this API. Lookups are always bounded to the verified customer."
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerSupportMessageCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerSupportMessage"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Ärendet hittades inte för den verifierade kunden.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Closed cases reject new messages with 409. Requires an actively linked portal user. Internal notes, phone logs and technical case events are never returned. Closure versus replay: authentication, scope and case ownership are always checked first. A retry with the same Idempotency-Key and the same payload of a write that already succeeded replays the original result (Idempotency-Replayed: true, nothing new is stored) even if the case was closed in between; a new write on a closed case returns 409 support_case_closed.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/support/cases/{reference}/attachments": {
      "get": {
        "operationId": "getApiV1CustomerSupportCasesReferenceAttachments",
        "summary": "List released attachments of a support case",
        "security": [
          {
            "bearerAuth": [
              "customer_support.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public case reference returned by this API. Lookups are always bounded to the verified customer."
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Opaque continuation value from X-Gridex-Next-Cursor of the previous response. Bound to the organization, the verified customer and the case; a modified or foreign cursor returns 400 invalid_cursor. Without cursor the first page is returned, identical to earlier V1 behaviour."
          }
        ],
        "responses": {
          "200": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerSupportAttachment"
                      }
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Next-Cursor": {
                "description": "Present only when another page exists. Send the value unchanged as the cursor query parameter to read the next page; absent on the last page.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering. invalid_cursor: the cursor was modified, expired or belongs to another case, customer or organization.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Ärendet hittades inte för den verifierade kunden.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Requires an actively linked portal user. Only released (content-checked), customer-visible attachments are ever listed or served; internal staff files are never returned. Returns customer-visible attachments oldest first, at most 100 per response. When more exist the response carries X-Gridex-Next-Cursor; repeat with ?cursor=<value> until the header is absent. The response body shape is unchanged.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      },
      "post": {
        "operationId": "postApiV1CustomerSupportCasesReferenceAttachments",
        "summary": "Upload an attachment to an open support case",
        "security": [
          {
            "bearerAuth": [
              "customer_support.write"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.write"
        ],
        "x-idempotency-required": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public case reference returned by this API. Lookups are always bounded to the verified customer."
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "X-File-Name",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "URL-encoded original file name. Informational only: it is sanitized and its extension is replaced by the detected type."
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary",
                "maxLength": 4194304
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary",
                "maxLength": 4194304
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary",
                "maxLength": 4194304
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lyckat svar.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "request_id",
                    "contract_schema_version"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerSupportAttachment"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "correlation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contract_schema_version": {
                      "type": "string",
                      "const": "2026-10-09.1"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Ärendet hittades inte för den verifierade kunden.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt. idempotency_reconciliation_required: an earlier attempt with this Idempotency-Key stopped without a confirmed result; check the resource state before using a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "413": {
            "description": "Filen är större än 4 MB.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "415": {
            "description": "Content-Type måste vara application/pdf, image/png eller image/jpeg.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "idempotency_completion_uncertain: the write may already be saved but its receipt could not be confirmed. Retry with the same Idempotency-Key and payload, never with a new key.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Send the raw file as the request body with Content-Type application/pdf, image/png or image/jpeg (at most 4 MB) and an optional URL-encoded X-File-Name header. The file is stored in quarantine and released only after a content check (real type from the bytes, no active PDF content such as JavaScript, launch actions or embedded files). Rejected files return 422 and are never served. Closed cases return 409. At most 20 attachments per customer per 24 hours (429). The same Idempotency-Key with the same bytes replays the result. Requires an actively linked portal user. Only released (content-checked), customer-visible attachments are ever listed or served; internal staff files are never returned. Closure versus replay: authentication, scope and case ownership are always checked first. A retry with the same Idempotency-Key and the same payload of a write that already succeeded replays the original result (Idempotency-Replayed: true, nothing new is stored) even if the case was closed in between; a new write on a closed case returns 409 support_case_closed.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "write",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/customer/support/cases/{reference}/attachments/{attachmentReference}": {
      "get": {
        "operationId": "getApiV1CustomerSupportCasesReferenceAttachmentsAttachmentReference",
        "summary": "Download a released attachment",
        "security": [
          {
            "bearerAuth": [
              "customer_support.read"
            ]
          },
          {
            "legacyApiKeyAuth": []
          }
        ],
        "x-required-scopes": [
          "customer_support.read"
        ],
        "x-idempotency-required": false,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public case reference returned by this API. Lookups are always bounded to the verified customer."
          },
          {
            "name": "attachmentReference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            },
            "description": "Public attachment reference returned by this API. Lookups are bounded to the verified customer and case."
          },
          {
            "$ref": "#/components/parameters/ExternalCustomerId"
          },
          {
            "$ref": "#/components/parameters/CustomerNumber"
          },
          {
            "$ref": "#/components/parameters/CustomerEmail"
          },
          {
            "name": "x-gridex-customer-portal-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-auth-user-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "x-gridex-customer-assertion",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 8192,
              "pattern": "^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$"
            },
            "description": "Signed proof of the end customer's own login, forwarded by the tenant server. Compact JWS signed with RS256, PS256 or ES256 (none and HS* are rejected). Claims: iss and aud as configured for the tenant in OPS (own-login keys use iss=gridex-tenant:<organization> and aud=gridex-customer-api:<organization>), sub = the linked portal user id, exp at most 15 minutes after iat, and a unique jti (each assertion is accepted once). Required only when the tenant has enabled \"require verified customer\"; in report mode a missing or invalid assertion is logged but the call proceeds; tenants without a configuration are unaffected."
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment bytes.",
            "headers": {
              "X-Gridex-Sha256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[0-9a-f]{64}$"
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Ogiltig JSON eller validering.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Token saknas eller är ogiltig.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Scope, IP eller origin tillåts inte. When the tenant requires a verified customer login: customer_assertion_required (header missing) or customer_assertion_invalid (signature, issuer, audience, subject, lifetime or replay check failed).",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Ärendet hittades inte för den verifierade kunden.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "409": {
            "description": "Tvetydig matchning eller idempotenskonflikt.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/OrganizationGone"
          },
          "422": {
            "description": "Affärsvalidering misslyckades.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/OrganizationPaused"
          },
          "429": {
            "description": "API-klientens trafikgräns har överskridits.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "500": {
            "description": "Internt fel utan databasdetaljer.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "503": {
            "description": "The required service or configured credential response profile is unavailable. Profile configuration errors require an operator correction.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "$ref": "#/components/headers/GridexContractVersion"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "X-Gridex-Documentation-Version": {
                "$ref": "#/components/headers/GridexDocumentationVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "description": "Returns the file bytes as an attachment download (Content-Disposition: attachment, X-Content-Type-Options: nosniff, sandboxing Content-Security-Policy). X-Gridex-Sha256 carries the verified SHA-256. A file whose bytes no longer match its recorded hash, or that is not released, is refused with 409. Requires an actively linked portal user. Only released (content-checked), customer-visible attachments are ever listed or served; internal staff files are never returned.",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-cache-policy": "no-store",
        "x-public-id-policy": "opaque-references"
      }
    },
    "/api/v1/openapi/2026-10-02.4/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-02.4",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-02.4.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.4"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-02.4"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610024CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-04.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-04.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-04.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-04.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-04.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610041CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-09.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-09.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-09.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-09.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-09.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610091CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    },
    "/api/v1/openapi/2026-10-12.1/customer-portal-v1.json": {
      "get": {
        "summary": "Immutable Customer Portal OpenAPI release 2026-10-12.1",
        "description": "Immutable Customer Portal OpenAPI release 2026-10-12.1.",
        "security": [],
        "responses": {
          "200": {
            "description": "Versionerad OpenAPI JSON",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-12.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "304": {
            "description": "Not Modified. The supplied If-None-Match value matches the current ETag.",
            "headers": {
              "X-Gridex-Contract-Version": {
                "description": "Revision of the OpenAPI document being fetched; business responses use x-contract-schema-version.",
                "schema": {
                  "type": "string",
                  "const": "2026-10-12.1"
                }
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Vary": {
                "$ref": "#/components/headers/Vary"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "Content-Type": {
                "$ref": "#/components/headers/ContentType"
              },
              "Content-Disposition": {
                "$ref": "#/components/headers/ContentDisposition"
              }
            }
          }
        },
        "x-required-scopes": [],
        "operationId": "getApiV1Openapi202610121CustomerPortalV1Json",
        "x-scope-mode": "all",
        "x-rate-limit-class": "read",
        "x-idempotency-required": false,
        "x-cache-policy": "public-immutable",
        "x-public-id-policy": "none"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Gridex API token"
      },
      "legacyApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "deprecated": true,
        "description": "Deprecated compatibility header. New integrations MUST use Authorization: Bearer <GRIDEX_API_KEY>. Sunset: 2026-10-31T23:59:59.000Z."
      }
    },
    "parameters": {
      "RequestId": {
        "name": "x-request-id",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 200
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 200,
          "pattern": "^[A-Za-z0-9._:+~-]+$"
        }
      },
      "ExternalCustomerId": {
        "name": "x-gridex-external-customer-id",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 200
        }
      },
      "CustomerNumber": {
        "name": "x-gridex-customer-number",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 100
        }
      },
      "CustomerEmail": {
        "name": "x-gridex-customer-email",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "format": "email"
        }
      },
      "CustomerPortalUserId": {
        "name": "x-gridex-customer-portal-user-id",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "AuthUserId": {
        "name": "x-gridex-auth-user-id",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Ogiltig JSON eller validering.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "code",
                "message"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "stage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "field": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "hint": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "Unauthorized": {
        "description": "Token saknas eller är ogiltig.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "code",
                "message"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "stage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "field": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "hint": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "Forbidden": {
        "description": "Scope, IP eller origin tillåts inte.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "code",
                "message"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "stage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "field": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "hint": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "Conflict": {
        "description": "Tvetydig matchning eller idempotenskonflikt.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "code",
                "message"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "stage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "field": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "hint": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "Unprocessable": {
        "description": "Affärsvalidering misslyckades.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "code",
                "message"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "stage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "field": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "hint": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "RateLimited": {
        "description": "API-klientens trafikgräns har överskridits.",
        "headers": {
          "Retry-After": {
            "description": "Sekunder till nästa tillåtna försök.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "API-klientens trafikgräns har överskridits. Försök igen när rate-limit-fönstret har återställts."
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Internt fel utan databasdetaljer.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "code",
                "message"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "stage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "field": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "hint": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string"
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Tjänsten eller ett obligatoriskt skydd är tillfälligt otillgängligt.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "object",
                  "required": [
                    "code",
                    "message"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "examples": {
              "rateLimiterUnavailable": {
                "value": {
                  "error": {
                    "code": "api_rate_limiter_unavailable",
                    "message": "API:ts trafikskydd kunde inte verifieras. Försök igen senare."
                  }
                }
              },
              "invalidRateLimit": {
                "value": {
                  "error": {
                    "code": "api_rate_limit_invalid",
                    "message": "API-klientens trafikgräns är felkonfigurerad."
                  }
                }
              }
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "Gone": {
        "description": "Endpoint removed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "OrganizationGone": {
        "description": "Organization is closed or inactive. Error codes: organization_closed, organization_inactive.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      },
      "OrganizationPaused": {
        "description": "Organization API access is paused. Error codes: organization_paused.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            }
          }
        },
        "headers": {
          "X-Gridex-Contract-Version": {
            "$ref": "#/components/headers/GridexContractVersion"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "X-Gridex-Documentation-Version": {
            "$ref": "#/components/headers/GridexDocumentationVersion"
          }
        }
      }
    },
    "schemas": {
      "PortfolioSettlementPermission": {
        "type": "string",
        "description": "Gridex-behörigheter är default-deny och får endast delegeras av platform_superadmin med organization-, portfölj- och tids-scope. manage_access kan aldrig delegeras.",
        "enum": [
          "portfolio_settlement.read",
          "portfolio_settlement.create",
          "portfolio_settlement.import",
          "portfolio_settlement.calculate",
          "portfolio_settlement.review",
          "portfolio_settlement.approve",
          "portfolio_settlement.lock",
          "portfolio_settlement.correct",
          "portfolio_settlement.manage_access"
        ]
      },
      "PortfolioHistoricalFinalPrice": {
        "type": "object",
        "required": [
          "period_month",
          "price_area_code",
          "amount",
          "unit",
          "vat_included",
          "status"
        ],
        "properties": {
          "period_month": {
            "type": "string",
            "format": "date",
            "description": "Historisk leveransmånad."
          },
          "price_area_code": {
            "type": "string",
            "enum": [
              "SE1",
              "SE2",
              "SE3",
              "SE4"
            ]
          },
          "amount": {
            "type": "number",
            "description": "Historiskt slutpris i öre/kWh exklusive moms."
          },
          "unit": {
            "type": "string",
            "const": "ore_per_kwh"
          },
          "vat_included": {
            "type": "boolean",
            "const": false
          },
          "status": {
            "type": "string",
            "enum": [
              "final",
              "locked"
            ]
          }
        },
        "additionalProperties": false
      },
      "ApiError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error",
          "request_id",
          "correlation_id",
          "contract_schema_version"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "retryable",
              "field",
              "blockers"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "stage": {
                "type": "string"
              },
              "field": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "hint": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "blockers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ApiBlocker"
                }
              },
              "details": {
                "type": [
                  "object",
                  "array",
                  "string",
                  "number",
                  "boolean",
                  "null"
                ]
              }
            }
          },
          "request_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": "string"
          },
          "contract_schema_version": {
            "type": "string",
            "const": "2026-10-09.1"
          }
        },
        "description": "Canonical error envelope. Business and provider failures use one nested error object; no parallel top-level aliases are emitted."
      },
      "CustomerContract": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "contract_reference",
          "status"
        ],
        "properties": {
          "contract_reference": {
            "type": "string"
          },
          "contract_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "offer_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "contract_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "contract_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "energy_direction": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "end_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "signed_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "withdrawal_deadline_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Stored withdrawal deadline. For newly signed qualifying private distance agreements, this is the end of the fourteenth calendar day after the acceptance date in Europe/Stockholm. Use the returned stored timestamp; previously frozen agreements retain their recorded deadline. Null means no deadline is applicable or recorded."
          },
          "signature_snapshot_sha256": {
            "type": [
              "string",
              "null"
            ]
          },
          "price_area": {
            "type": [
              "string",
              "null"
            ]
          },
          "monthly_fee_sek": {
            "type": [
              "number",
              "null"
            ]
          },
          "invoice_fee_sek": {
            "type": [
              "number",
              "null"
            ]
          },
          "fixed_price_ore_per_kwh": {
            "type": [
              "number",
              "null"
            ]
          },
          "markup_ore_per_kwh": {
            "type": [
              "number",
              "null"
            ]
          },
          "binding_months": {
            "type": [
              "number",
              "null"
            ]
          },
          "notice_months": {
            "type": [
              "number",
              "null"
            ]
          },
          "auto_renew_enabled": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PublicPricingVisibility": {
        "type": "object",
        "description": "Versionslåsta presentationsregler. False döljer endast separat rendering och får aldrig filtrera bort komponenten från API eller kalkyl.",
        "properties": {
          "fixed_price": {
            "type": "boolean"
          },
          "spot_markup": {
            "type": "boolean"
          },
          "variable_fee": {
            "type": "boolean"
          },
          "monthly_fee": {
            "type": "boolean"
          },
          "invoice_fee": {
            "type": "boolean"
          },
          "green_energy_fee": {
            "type": "boolean"
          },
          "electricity_certificate": {
            "type": "boolean"
          },
          "start_fee": {
            "type": "boolean"
          },
          "administration_fee": {
            "type": "boolean"
          },
          "break_fee": {
            "type": "boolean"
          },
          "portfolio_management_fee": {
            "type": "boolean"
          },
          "campaign_discount": {
            "type": "boolean"
          },
          "optional_fees": {
            "type": "boolean"
          },
          "production_compensation": {
            "type": "boolean"
          },
          "portfolio_price": {
            "type": "boolean",
            "description": "Controls current/monthly portfolio price rendering on the public contract card."
          }
        },
        "additionalProperties": false
      },
      "PublicPricingComponent": {
        "type": "object",
        "required": [
          "component_code",
          "component_type",
          "name",
          "amount",
          "unit",
          "website_card_visible",
          "calculation_inclusion",
          "website_visibility"
        ],
        "properties": {
          "component_code": {
            "type": "string"
          },
          "component_type": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "unit": {
            "type": "string",
            "description": "Canonical unit, including percent, ore_per_kwh, sek_per_kwh, sek_month, sek_invoice or sek_once."
          },
          "calculation_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "website_card_visible": {
            "type": "boolean",
            "description": "Kompatibilitetsalias. Använd website_visibility.",
            "deprecated": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "calculation_base": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PricingCalculationBase"
              },
              {
                "type": "null"
              }
            ]
          },
          "calculation_inclusion": {
            "$ref": "#/components/schemas/CalculationInclusion"
          },
          "website_visibility": {
            "$ref": "#/components/schemas/WebsiteVisibilityMode"
          }
        },
        "additionalProperties": true,
        "description": "Maskinläsbar pris- eller avgiftskomponent. Alla tillämpliga komponenter returneras oavsett presentationsstatus."
      },
      "PricingCalculationBase": {
        "type": "string",
        "enum": [
          "energy_cost_ex_vat",
          "energy_cost_inc_vat",
          "spot_cost",
          "portfolio_cost",
          "total_variable_cost",
          "invoice_subtotal",
          "monthly_fixed_amount"
        ],
        "description": "Obligatorisk för procentkomponenter. Procentvärden representeras alltid som 0–100."
      },
      "PortfolioMonthlyPrice": {
        "type": "object",
        "required": [
          "period_month",
          "price_area_code",
          "amount",
          "unit",
          "vat_included",
          "status"
        ],
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "price_plan_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "price_plan_version_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "period_month": {
            "type": "string",
            "format": "date",
            "description": "Historisk avräkningsmånad, alltid första kalenderdatum YYYY-MM-01. Fältet beskriver aldrig ett framtida faktiskt pris."
          },
          "price_area_code": {
            "type": "string",
            "enum": [
              "SE1",
              "SE2",
              "SE3",
              "SE4"
            ]
          },
          "amount": {
            "type": "number",
            "description": "Öre/kWh exklusive moms. Kan vara noll eller negativt när det publicerade marknadsutfallet kräver det.",
            "minimum": -100000,
            "maximum": 100000
          },
          "unit": {
            "type": "string",
            "const": "ore_per_kwh"
          },
          "vat_included": {
            "type": "boolean",
            "const": false
          },
          "status": {
            "type": "string",
            "enum": [
              "final",
              "locked"
            ]
          },
          "source": {
            "type": [
              "string",
              "null"
            ]
          },
          "version_number": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "locked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "PortfolioPriceDisplay": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "period_month": {
            "type": "string",
            "format": "date"
          },
          "unit": {
            "type": "string",
            "const": "ore_per_kwh"
          },
          "vat_included": {
            "type": "boolean",
            "const": false
          },
          "prices_by_area": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          }
        },
        "additionalProperties": false
      },
      "CalculationInclusion": {
        "type": "string",
        "enum": [
          "included",
          "excluded",
          "conditional"
        ],
        "description": "Anger hur komponenten ska användas i the organization's prisberäkning."
      },
      "ContractPriceValue": {
        "type": "object",
        "required": [
          "amount",
          "unit",
          "vat_included",
          "calculation_inclusion",
          "website_visibility"
        ],
        "properties": {
          "amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "vat_included": {
            "type": "boolean"
          },
          "vat_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Decimal VAT fraction; 0.25 means 25%. Newly authored standard consumption prices use 0.25. Explicit production or exempt treatment and frozen historical values retain their recorded rate."
          },
          "calculation_inclusion": {
            "$ref": "#/components/schemas/CalculationInclusion"
          },
          "website_visibility": {
            "$ref": "#/components/schemas/WebsiteVisibilityMode"
          }
        },
        "additionalProperties": true,
        "description": "Publicerat avtalsvärde. Returneras även när website_visibility är hidden."
      },
      "CustomerInvoice": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "invoice_reference",
          "status"
        ],
        "properties": {
          "invoice_reference": {
            "type": "string"
          },
          "invoice_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "period_start": {
            "type": [
              "string",
              "null"
            ]
          },
          "period_end": {
            "type": [
              "string",
              "null"
            ]
          },
          "total_kwh": {
            "type": [
              "number",
              "null"
            ]
          },
          "amount_ex_vat": {
            "type": [
              "number",
              "null"
            ]
          },
          "vat_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "amount_inc_vat": {
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "type": "string"
          },
          "issued_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "paid_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "IntegrationContext": {
        "type": "object",
        "required": [
          "organization_reference",
          "api_client_reference",
          "api_version",
          "authoritative_identity",
          "contract_version",
          "configuration",
          "capabilities"
        ],
        "properties": {
          "organization_reference": {
            "type": "string",
            "pattern": "^organization_[A-Za-z0-9_-]{20,64}$",
            "description": "Stable opaque public reference for the organization associated with the authenticated API credential."
          },
          "api_client_reference": {
            "type": "string"
          },
          "api_version": {
            "const": "v1"
          },
          "authoritative_identity": {
            "const": "api_key"
          },
          "contract_version": {
            "const": "2026-10-09.1"
          },
          "configuration": {
            "type": "object",
            "required": [
              "required_environment_variables",
              "api_base_url",
              "authentication",
              "openapi_url",
              "application_reference_location"
            ],
            "properties": {
              "required_environment_variables": {
                "type": "array",
                "prefixItems": [
                  {
                    "const": "GRIDEX_API_KEY"
                  }
                ],
                "minItems": 1,
                "maxItems": 1
              },
              "api_base_url": {
                "const": "https://app.gridex.se/api/v1"
              },
              "authentication": {
                "type": "object",
                "required": [
                  "header",
                  "scheme",
                  "server_side_only"
                ],
                "properties": {
                  "header": {
                    "const": "Authorization"
                  },
                  "scheme": {
                    "const": "Bearer"
                  },
                  "server_side_only": {
                    "const": true
                  }
                }
              },
              "openapi_url": {
                "const": "https://app.gridex.se/api/v1/openapi/website-integration-v1.json"
              },
              "customer_portal_openapi_url": {
                "const": "https://app.gridex.se/api/v1/openapi/customer-portal-v1.json"
              },
              "application_reference_location": {
                "const": "top_level"
              }
            },
            "additionalProperties": false
          },
          "capabilities": {
            "type": "object",
            "required": [
              "website_checkout_ready",
              "customer_portal_ready",
              "complete_integration_ready",
              "missing_website_scopes",
              "missing_customer_portal_scopes",
              "missing_recommended_scopes"
            ],
            "properties": {
              "website_checkout_ready": {
                "type": "boolean"
              },
              "customer_portal_ready": {
                "type": "boolean"
              },
              "complete_integration_ready": {
                "type": "boolean",
                "description": "True when the configured website checkout and customer portal capabilities are ready for production use."
              },
              "required_website_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "missing_website_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "required_customer_portal_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "missing_customer_portal_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "recommended_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "missing_recommended_scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "additionalProperties": false
          }
        }
      },
      "EnergyDirection": {
        "type": "string",
        "enum": [
          "consumption",
          "production"
        ],
        "description": "Canonical economic direction. Consumption creates ordinary supply/invoice flows; production creates compensation settlement flows."
      },
      "ApiBlocker": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "field": {
            "type": [
              "string",
              "null"
            ]
          },
          "resource_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "resource_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "recommended_action": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error",
          "request_id",
          "correlation_id",
          "contract_schema_version"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "retryable",
              "field",
              "blockers"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "stage": {
                "type": "string"
              },
              "field": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "hint": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "blockers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ApiBlocker"
                }
              },
              "details": {
                "type": [
                  "object",
                  "array",
                  "string",
                  "number",
                  "boolean",
                  "null"
                ]
              }
            }
          },
          "request_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": "string"
          },
          "contract_schema_version": {
            "type": "string",
            "const": "2026-10-09.1"
          }
        },
        "description": "Canonical error envelope. Business and provider failures use one nested error object; no parallel top-level aliases are emitted."
      },
      "WebsiteVisibilityMode": {
        "type": "string",
        "enum": [
          "visible",
          "hidden",
          "summary_only"
        ]
      },
      "PortalSyncRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "external_customer_id",
          "customer_portal_user_id",
          "auth_user_id"
        ],
        "properties": {
          "external_customer_id": {
            "type": "string"
          },
          "external_account_id": {
            "type": "string"
          },
          "customer_portal_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "auth_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "personal_number": {
            "type": "string"
          },
          "organization_number": {
            "type": "string"
          },
          "customer_number": {
            "type": "string"
          },
          "facility_id": {
            "type": "string"
          },
          "metadata": {
            "type": "object"
          }
        },
        "dependentRequired": {
          "auth_user_id": [
            "customer_portal_user_id"
          ],
          "customer_portal_user_id": [
            "auth_user_id"
          ]
        }
      },
      "PortalSyncData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "access_granted"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "linked",
              "pending_review",
              "rejected"
            ]
          },
          "outcome": {
            "type": "string",
            "enum": [
              "linked",
              "pending_review",
              "lead_created",
              "rejected"
            ]
          },
          "customer_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "external_customer_id": {
            "type": "string"
          },
          "customer_portal_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "auth_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "portal_role": {
            "type": "string",
            "enum": [
              "owner",
              "billing",
              "viewer"
            ]
          },
          "created": {
            "type": "boolean"
          },
          "access_granted": {
            "type": "boolean"
          },
          "reason": {
            "type": "string"
          },
          "identity_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ClosedPortalResourceEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "request_id",
          "contract_schema_version"
        ],
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {}
              },
              {
                "type": "null"
              }
            ]
          },
          "request_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "contract_schema_version": {
            "type": "string",
            "const": "2026-10-09.1"
          },
          "page": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PortalPage"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "sites"
                ],
                "properties": {
                  "sites": {
                    "$ref": "#/components/schemas/PortalPage"
                  }
                }
              }
            ]
          }
        }
      },
      "ClosedPortalMutationRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "object"
          },
          "notification_references": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            }
          },
          "external_customer_id": {
            "type": "string"
          },
          "customer_number": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "auth_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "customer_portal_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "facility_data": {
            "type": "object"
          },
          "profile": {
            "type": "object"
          },
          "requested_move_out_date": {
            "type": "string",
            "format": "date"
          },
          "reason": {
            "type": "string"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "CustomerSyncRequest": {
        "type": "object",
        "additionalProperties": false,
        "anyOf": [
          {
            "required": [
              "email"
            ]
          },
          {
            "required": [
              "customer_number"
            ]
          },
          {
            "required": [
              "external_customer_id"
            ]
          },
          {
            "required": [
              "authenticated_user_reference"
            ]
          }
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320
          },
          "customer_number": {
            "type": "string",
            "maxLength": 100
          },
          "external_customer_id": {
            "type": "string",
            "maxLength": 200
          },
          "authenticated_user_reference": {
            "type": "string",
            "maxLength": 200,
            "description": "Authenticated customer's account or user subject from the organization's login system. Resolves an already linked active portal account or identity within the API credential's organization (external account subject; portal/Auth user UUID aliases are supported). This is not a central Gridex database ID or an opaque Gridex public reference. An unlinked, disabled or other-organization subject never grants access or creates a link; email and customer-number matches alone do not establish identity."
          },
          "profile": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "first_name": {
                "type": "string"
              },
              "last_name": {
                "type": "string"
              },
              "full_name": {
                "type": "string"
              },
              "company_name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "invoice_email": {
                "type": "string",
                "format": "email"
              },
              "language_code": {
                "type": "string"
              },
              "timezone": {
                "type": "string"
              }
            }
          },
          "facility_data": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "facility_reference": {
                  "type": "string"
                },
                "facility_id": {
                  "type": "string"
                },
                "metering_point_id": {
                  "type": "string"
                },
                "move_in_date": {
                  "type": "string",
                  "format": "date"
                },
                "requested_start_date": {
                  "type": "string",
                  "format": "date"
                },
                "address": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "street": {
                      "type": "string"
                    },
                    "postal_code": {
                      "type": "string"
                    },
                    "city": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "care_of": {
                      "type": "string"
                    },
                    "apartment_number": {
                      "type": "string"
                    }
                  }
                },
                "metadata": {
                  "type": "object"
                }
              }
            }
          },
          "documents": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "document_reference": {
                  "type": "string"
                },
                "document_type": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "secure_url": {
                  "type": "string",
                  "format": "uri"
                },
                "file_name": {
                  "type": "string"
                },
                "mime_type": {
                  "type": "string"
                },
                "file_size_bytes": {
                  "type": "integer",
                  "minimum": 0
                },
                "metadata": {
                  "type": "object"
                }
              }
            }
          },
          "legal_acceptances": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "document_reference",
                "document_code",
                "document_version",
                "document_hash",
                "accepted",
                "accepted_at"
              ],
              "properties": {
                "document_reference": {
                  "type": "string"
                },
                "document_code": {
                  "type": "string"
                },
                "document_version": {
                  "type": "string"
                },
                "document_hash": {
                  "type": "string",
                  "pattern": "^[a-fA-F0-9]{64}$"
                },
                "accepted": {
                  "type": "boolean",
                  "const": true
                },
                "accepted_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "metadata": {
                  "type": "object"
                }
              }
            }
          },
          "power_of_attorney": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "document_reference",
              "scope",
              "accepted",
              "accepted_at"
            ],
            "description": "organization-synkad fullmakt. signer_name, signer_identity_number och method krävs för att fullmakten ska bli signerad och externt sändbar; äldre payload utan dessa lagras endast som ett ofullständigt utkast och blockerar leverantörsbyte.",
            "properties": {
              "power_of_attorney_reference": {
                "type": "string"
              },
              "document_reference": {
                "type": "string",
                "description": "Accepterar både den nya customer_documents-referensen för power_of_attorney och äldre exakt module_version-referens från samma organization-scoped legal bundle."
              },
              "scope": {
                "type": "array",
                "minItems": 1,
                "maxItems": 2,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "enum": [
                    "supplier_switch",
                    "facility_information_lookup"
                  ]
                },
                "contains": {
                  "const": "supplier_switch"
                }
              },
              "accepted": {
                "type": "boolean",
                "const": true
              },
              "accepted_at": {
                "type": "string",
                "format": "date-time"
              },
              "signer_name": {
                "type": "string"
              },
              "signer_identity_number": {
                "type": "string"
              },
              "method": {
                "type": "string"
              },
              "ip_address": {
                "type": "string"
              },
              "user_agent": {
                "type": "string"
              },
              "valid_from": {
                "type": "string",
                "format": "date"
              },
              "valid_to": {
                "type": "string",
                "format": "date"
              },
              "metadata": {
                "type": "object"
              }
            }
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "CustomerMoveOutRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "facility_reference",
          "requested_move_out_date"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320
          },
          "customer_number": {
            "type": "string",
            "maxLength": 100
          },
          "external_customer_id": {
            "type": "string",
            "maxLength": 200
          },
          "authenticated_user_reference": {
            "type": "string",
            "maxLength": 200,
            "description": "Authenticated customer's account or user subject from the organization's login system. Resolves an already linked active portal account or identity within the API credential's organization (external account subject; portal/Auth user UUID aliases are supported). This is not a central Gridex database ID or an opaque Gridex public reference. An unlinked, disabled or other-organization subject never grants access or creates a link; email and customer-number matches alone do not establish identity."
          },
          "customer_contract_reference": {
            "type": "string"
          },
          "facility_reference": {
            "type": "string"
          },
          "requested_move_out_date": {
            "type": "string",
            "format": "date"
          },
          "reason": {
            "type": "string"
          },
          "new_address": {
            "type": "object"
          },
          "contact_details": {
            "type": "object"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "CustomerSyncData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "customer_reference",
          "summary"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "synced"
          },
          "customer_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "external_customer_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "summary": {
            "type": "object"
          }
        }
      },
      "CustomerMoveOutData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "completion_reference",
          "customer_reference",
          "facility_reference",
          "requested_move_out_date",
          "status",
          "replayed"
        ],
        "properties": {
          "completion_reference": {
            "type": "string"
          },
          "customer_reference": {
            "type": "string"
          },
          "facility_reference": {
            "type": "string"
          },
          "contract_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "requested_move_out_date": {
            "type": "string",
            "format": "date"
          },
          "status": {
            "type": "string",
            "const": "submitted"
          },
          "replayed": {
            "type": "boolean"
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "description": "Server-issued timestamp of the stored move-out completion, retained on replay."
          }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error",
          "request_id",
          "correlation_id",
          "contract_schema_version"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "retryable",
              "field",
              "blockers"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "stage": {
                "type": "string"
              },
              "field": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "hint": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "blockers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ApiBlocker"
                }
              },
              "details": {
                "type": [
                  "object",
                  "array",
                  "string",
                  "number",
                  "boolean",
                  "null"
                ]
              }
            }
          },
          "request_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": "string"
          },
          "contract_schema_version": {
            "type": "string",
            "const": "2026-10-09.1"
          }
        },
        "description": "Canonical error envelope. Business and provider failures use one nested error object; no parallel top-level aliases are emitted."
      },
      "MarketPriceErrorEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error",
          "request_id",
          "correlation_id",
          "contract_schema_version"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "code",
              "message",
              "retryable",
              "field",
              "blockers"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "stage": {
                "type": "string"
              },
              "field": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "hint": {
                "type": "string"
              },
              "retryable": {
                "type": "boolean"
              },
              "blockers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ApiBlocker"
                }
              },
              "details": {
                "type": [
                  "object",
                  "array",
                  "string",
                  "number",
                  "boolean",
                  "null"
                ]
              }
            }
          },
          "request_id": {
            "type": "string"
          },
          "correlation_id": {
            "type": "string"
          },
          "contract_schema_version": {
            "type": "string",
            "const": "2026-10-09.1"
          }
        },
        "description": "Canonical error envelope. Business and provider failures use one nested error object; no parallel top-level aliases are emitted."
      },
      "CustomerNotificationReadRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "notification_references"
        ],
        "properties": {
          "notification_references": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "items": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            }
          }
        }
      },
      "CustomerNotificationReadData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "updated_count",
          "notification_references",
          "read_at"
        ],
        "properties": {
          "updated_count": {
            "type": "integer",
            "minimum": 0
          },
          "notification_references": {
            "type": "array",
            "items": {
              "type": [
                "string",
                "null"
              ],
              "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
            }
          },
          "read_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CustomerProfile": {
        "type": "object",
        "additionalProperties": false,
        "required": [],
        "properties": {
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "full_name": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string"
          },
          "invoice_email": {
            "type": "string",
            "format": "email"
          },
          "language_code": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          }
        },
        "minProperties": 1
      },
      "CustomerFacilityUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "facility_reference",
          "address"
        ],
        "properties": {
          "facility_reference": {
            "type": "string"
          },
          "address": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {
              "street": {
                "type": "string"
              },
              "postal_code": {
                "type": "string"
              },
              "city": {
                "type": "string"
              },
              "country": {
                "type": "string"
              },
              "care_of": {
                "type": "string"
              },
              "apartment_number": {
                "type": "string"
              }
            },
            "minProperties": 1
          },
          "external_request_id": {
            "type": "string"
          }
        }
      },
      "CustomerProfileUpdateRequest": {
        "type": "object",
        "additionalProperties": false,
        "anyOf": [
          {
            "required": [
              "profile"
            ]
          },
          {
            "required": [
              "facility_data"
            ]
          }
        ],
        "properties": {
          "profile": {
            "$ref": "#/components/schemas/CustomerProfile"
          },
          "facility_data": {
            "$ref": "#/components/schemas/CustomerFacilityUpdate"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "CustomerProfileUpdateData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "completion_reference",
          "status",
          "created_at",
          "profile_updated",
          "facility_updated",
          "address_result"
        ],
        "properties": {
          "completion_reference": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "profile_updated": {
            "type": "boolean"
          },
          "facility_updated": {
            "type": "boolean"
          },
          "address_result": {
            "type": [
              "object",
              "null"
            ]
          }
        }
      },
      "CustomerEventIdentity": {
        "type": "object",
        "additionalProperties": false,
        "required": [],
        "properties": {
          "external_customer_id": {
            "type": "string"
          },
          "customer_number": {
            "type": "string"
          },
          "auth_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "customer_portal_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
          },
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "CustomerEventRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "event_type",
          "event_reference",
          "occurred_at",
          "customer",
          "subject",
          "data"
        ],
        "properties": {
          "event_type": {
            "type": "string",
            "pattern": "^customer\\.[a-z0-9_]+$"
          },
          "event_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "customer": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {
              "external_customer_id": {
                "type": "string"
              },
              "customer_number": {
                "type": "string"
              },
              "auth_user_id": {
                "type": "string",
                "format": "uuid",
                "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
              },
              "customer_portal_user_id": {
                "type": "string",
                "format": "uuid",
                "description": "Optional verified organization-portal user UUID. Must be supplied together with auth_user_id and must match it."
              },
              "email": {
                "type": "string",
                "format": "email"
              }
            }
          },
          "subject": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "reference": {
                "type": "string"
              }
            }
          },
          "data": {
            "type": "object"
          },
          "metadata": {
            "type": "object"
          }
        }
      },
      "CustomerEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "event_reference",
          "event_resource_reference",
          "event_type",
          "customer_reference",
          "status",
          "occurred_at",
          "replayed"
        ],
        "properties": {
          "event_reference": {
            "type": "string"
          },
          "event_resource_reference": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
          },
          "event_type": {
            "type": "string"
          },
          "customer_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "const": "accepted"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "replayed": {
            "type": "boolean"
          }
        }
      },
      "PublicDomainEvent": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "event_id",
          "event_type",
          "created_at",
          "organization_reference",
          "environment",
          "aggregate",
          "data",
          "contract_schema_version"
        ],
        "properties": {
          "event_id": {
            "type": "string"
          },
          "event_type": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "organization_reference": {
            "type": "string",
            "pattern": "^organization_[A-Za-z0-9_-]{20,64}$",
            "description": "Stable opaque public reference for the organization associated with the authenticated API credential."
          },
          "environment": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "test",
              "production",
              null
            ]
          },
          "aggregate": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "reference"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "reference": {
                "type": "string"
              }
            }
          },
          "customer": {
            "type": "object",
            "additionalProperties": false,
            "required": [],
            "properties": {
              "customer_reference": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "customer_number": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "data": {
            "type": "object"
          },
          "contract_schema_version": {
            "type": "string",
            "const": "2026-10-09.1"
          }
        }
      },
      "DomainEventListData": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/PublicDomainEvent"
        }
      },
      "CustomerSupportCase": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "case_reference",
          "title",
          "description",
          "status",
          "channel",
          "created_at",
          "updated_at",
          "resolved_at"
        ],
        "properties": {
          "case_reference": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$",
            "description": "Opaque public reference. It identifies the case but grants no access on its own."
          },
          "title": {
            "type": "string",
            "maxLength": 180
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only text the customer wrote when opening the case; null for staff-created cases."
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "in_progress",
              "resolved",
              "closed"
            ],
            "description": "Customer-visible status. Internal working states are not exposed."
          },
          "channel": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "api",
              "customer_portal",
              "admin",
              "phone",
              "operations_automation",
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "resolved_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "CustomerSupportMessage": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message_reference",
          "author_type",
          "kind",
          "body",
          "created_at"
        ],
        "properties": {
          "message_reference": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$"
          },
          "author_type": {
            "type": "string",
            "enum": [
              "customer",
              "staff"
            ],
            "description": "staff = a named employee of the organization; the employee identity is not exposed."
          },
          "kind": {
            "type": "string",
            "enum": [
              "message",
              "phone_summary"
            ],
            "description": "phone_summary = a call summary explicitly published by staff; never an authenticated customer message."
          },
          "body": {
            "type": "string",
            "maxLength": 8000
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CustomerSupportCaseDetail": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "case_reference",
          "title",
          "description",
          "status",
          "channel",
          "created_at",
          "updated_at",
          "resolved_at",
          "messages"
        ],
        "properties": {
          "case_reference": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$",
            "description": "Opaque public reference. It identifies the case but grants no access on its own."
          },
          "title": {
            "type": "string",
            "maxLength": 180
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only text the customer wrote when opening the case; null for staff-created cases."
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "in_progress",
              "resolved",
              "closed"
            ],
            "description": "Customer-visible status. Internal working states are not exposed."
          },
          "channel": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "api",
              "customer_portal",
              "admin",
              "phone",
              "operations_automation",
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "resolved_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerSupportMessage"
            }
          }
        }
      },
      "CustomerSupportCaseCreateRequest": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "title",
          "message"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 180
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 8000
          },
          "category": {
            "type": "string",
            "maxLength": 120
          }
        }
      },
      "CustomerSupportMessageCreateRequest": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 8000
          }
        }
      },
      "PortalPage": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "limit",
          "offset",
          "returned",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          },
          "returned": {
            "type": "integer",
            "minimum": 0
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CustomerSupportAttachment": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "attachment_reference",
          "file_name",
          "mime_type",
          "byte_size",
          "sha256",
          "uploaded_by",
          "created_at"
        ],
        "properties": {
          "attachment_reference": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{1,31}_[A-Za-z0-9_-]{20,64}$",
            "description": "Opaque public reference. It identifies the attachment but grants no access on its own."
          },
          "file_name": {
            "type": "string",
            "maxLength": 160,
            "description": "Sanitized file name; the extension always matches the detected type."
          },
          "mime_type": {
            "type": "string",
            "enum": [
              "application/pdf",
              "image/png",
              "image/jpeg"
            ],
            "description": "Type detected from the file content, never the declared type."
          },
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10485760
          },
          "sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "SHA-256 of the stored bytes; re-verified on every download."
          },
          "uploaded_by": {
            "type": "string",
            "enum": [
              "customer",
              "staff"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "OpenApiReleaseManifest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "release_version",
          "website_openapi_version",
          "customer_portal_openapi_version",
          "staff_openapi_version",
          "runtime_contract_version",
          "guide_version",
          "released_at",
          "generated_at",
          "build_commit",
          "compatibility_classification",
          "deprecated_features",
          "minimum_tenant_integration_version",
          "specifications"
        ],
        "properties": {
          "release_version": {
            "type": "string",
            "const": "2026-10-12.1"
          },
          "website_openapi_version": {
            "type": "string",
            "const": "2026-10-12.1"
          },
          "customer_portal_openapi_version": {
            "type": "string",
            "const": "2026-10-12.1"
          },
          "staff_openapi_version": {
            "type": "string",
            "const": "2026-10-12.1"
          },
          "runtime_contract_version": {
            "type": "string",
            "const": "2026-10-09.1"
          },
          "guide_version": {
            "type": "string",
            "const": "2026-10-12.1"
          },
          "released_at": {
            "type": "string",
            "format": "date-time"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "build_commit": {
            "type": "string"
          },
          "compatibility_classification": {
            "type": "string",
            "enum": [
              "backward-compatible",
              "breaking-client-update-required",
              "breaking"
            ]
          },
          "deprecated_features": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "feature",
                "replacement",
                "sunset_at"
              ],
              "properties": {
                "feature": {
                  "type": "string"
                },
                "replacement": {
                  "type": "string"
                },
                "sunset_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "minimum_tenant_integration_version": {
            "type": "string",
            "const": "2026-10-02.3"
          },
          "specifications": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "website",
              "customer_portal",
              "staff"
            ],
            "properties": {
              "website": {
                "$ref": "#/components/schemas/OpenApiReleaseSpecification"
              },
              "customer_portal": {
                "$ref": "#/components/schemas/OpenApiReleaseSpecification"
              },
              "staff": {
                "$ref": "#/components/schemas/OpenApiReleaseSpecification"
              }
            }
          }
        }
      },
      "OpenApiReleaseSpecification": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "contract_name",
          "contract_version",
          "url",
          "immutable_url",
          "sha256",
          "compatibility"
        ],
        "properties": {
          "contract_name": {
            "type": "string"
          },
          "contract_version": {
            "type": "string",
            "const": "2026-10-12.1"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "immutable_url": {
            "type": "string",
            "format": "uri"
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "compatibility": {
            "type": "string",
            "enum": [
              "backward-compatible",
              "breaking-client-update-required",
              "breaking"
            ]
          }
        }
      }
    },
    "headers": {
      "GridexContractVersion": {
        "description": "Canonical contract version used for this response.",
        "schema": {
          "type": "string",
          "const": "2026-10-09.1"
        }
      },
      "RequestId": {
        "description": "Stable request identifier for support and audit.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitLimit": {
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "RateLimitRemaining": {
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "RateLimitReset": {
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "RetryAfter": {
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "ETag": {
        "description": "Strong entity tag for conditional retrieval.",
        "schema": {
          "type": "string"
        }
      },
      "CacheControl": {
        "description": "Caching policy for this document.",
        "schema": {
          "type": "string"
        }
      },
      "ContentType": {
        "description": "Response media type.",
        "schema": {
          "type": "string"
        }
      },
      "ContentDisposition": {
        "description": "Suggested inline filename.",
        "schema": {
          "type": "string"
        }
      },
      "Vary": {
        "description": "Request headers that affect cache validation.",
        "schema": {
          "type": "string"
        }
      },
      "GridexDocumentationVersion": {
        "description": "Optional documentation revision associated with this business response. It does not change contract_schema_version or the supported wire schema.",
        "schema": {
          "type": "string",
          "const": "2026-10-12.1"
        }
      }
    }
  },
  "x-contract-schema-version": "2026-10-09.1",
  "x-gridex-organization-setup": {
    "required_environment_variables": [
      "GRIDEX_API_KEY"
    ],
    "api_base_url": "https://app.gridex.se/api/v1",
    "authentication": "Authorization: Bearer <GRIDEX_API_KEY>",
    "tenant_identity_source": "api_key",
    "application_reference_location": "top_level",
    "website_openapi_url": "https://app.gridex.se/api/v1/openapi/website-integration-v1.json",
    "customer_portal_openapi_url": "https://app.gridex.se/api/v1/openapi/customer-portal-v1.json"
  },
  "tags": [
    {
      "name": "Integration context",
      "description": "Verifiera API-nyckelns tenantkontext, fasta base URL och one-secret readiness."
    }
  ],
  "x-gridex-release-version": "2026-10-12.1",
  "x-error-codes": [
    "missing_api_token",
    "invalid_api_token",
    "api_token_expired",
    "api_client_inactive",
    "api_scope_missing",
    "api_ip_not_allowed",
    "api_origin_not_allowed",
    "rate_limited",
    "api_rate_limit_invalid",
    "api_rate_limiter_unavailable",
    "api_auth_unavailable",
    "organization_status_unavailable",
    "organization_not_operationally_ready",
    "organization_paused",
    "organization_closed",
    "organization_suspended",
    "organization_inactive",
    "platform_schema_not_ready",
    "PUBLIC_CONTRACT_FEED_INCONSISTENT",
    "PUBLICATION_GRAPH_INCONSISTENT",
    "PUBLIC_CONTRACT_SCHEMA_INVALID",
    "PUBLIC_CONTRACT_SCHEMA_OUTDATED",
    "PUBLIC_CONTRACTS_TEMPORARILY_UNAVAILABLE",
    "offer_reference_mismatch",
    "api_contract_profile_unavailable"
  ],
  "x-scope-aliases": {
    "customer_portal.read": {
      "status": "deprecated_legacy_alias",
      "expands_to": [
        "customer_profile.read",
        "customer_sites.read",
        "customer_contracts.read",
        "customer_invoices.read",
        "customer_metering.read",
        "customer_legal.read",
        "customer_events.read",
        "customer_documents.read",
        "customer_notifications.read",
        "customer_power_of_attorney.read"
      ],
      "replacement": "Grant the granular read scopes required by the routes used."
    },
    "customer_portal.write": {
      "status": "deprecated_legacy_alias",
      "expands_to": [
        "customer_sync.write",
        "customer_contact.write",
        "customer_facility_data.write",
        "customer_power_of_attorney.write",
        "customer_notifications.write",
        "customer_documents.write"
      ],
      "replacement": "Grant the granular write scopes required by the routes used."
    }
  }
}
