> ## Documentation Index
> Fetch the complete documentation index at: https://broker-docs.newyorkcityservers.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrade Service

> Submit a service plan upgrade for background processing.

Submit an upgrade from the current service plan to a higher plan. The API creates or reuses an upgrade request and starts background processing.

<Note>
  A successful response means that the API accepted the request. It does not mean that the plan change is complete.
</Note>

## Allowed Plan Changes

An upgrade must move from a lower plan to a higher plan in this order:

1. `Basic VPS`
2. `Standard VPS`
3. `Professional VPS`
4. `Dedicated Server`

The requested plan must be above the current plan.

| Current plan       | Valid upgrade plans                                    |
| ------------------ | ------------------------------------------------------ |
| `Basic VPS`        | `Standard VPS`, `Professional VPS`, `Dedicated Server` |
| `Standard VPS`     | `Professional VPS`, `Dedicated Server`                 |
| `Professional VPS` | `Dedicated Server`                                     |
| `Dedicated Server` | None                                                   |

Use the [downgrade endpoint](/api/services/downgrade) for a move to a lower plan.

## Accepted Response

The normal response is HTTP `200`. The plan change runs in background processing.

The response does not contain an action ID, a processed date, or a completion result. Use the request ID with the [list requests endpoint](/api/requests/list-requests) to check the request state.

## Upgrade Processing

A reboot of the client's service is required for finalizing the upgrade. Therefore, once an upgrade request is submitted the client will receive an email containing the next required steps to complete the upgrade process.

The upgrade to the client's service is not applied until they perform the required steps.

## Errors

| HTTP status | Error code                     | Cause                                                                                                                               |
| ----------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `400`       | `invalid_parameter`            | The service number is invalid, or the plan is not supported.                                                                        |
| `400`       | `invalid_request`              | The request body is not valid JSON.                                                                                                 |
| `400`       | `missing_parameter`            | `new_plan` is missing, is blank, or is not a string.                                                                                |
| `400`       | `invalid_state`                | The target is the current plan, the target is lower, the current plan is not recognized, or the service is cancelled or terminated. |
| `400`       | `service_pending_provisioning` | The service is still pending provisioning.                                                                                          |
| `401`       | `authentication_failed`        | The Bearer token is missing, invalid, inactive, or expired.                                                                         |
| `403`       | `insufficient_permissions`     | The caller IP is not allowed or the key does not have `admin:full`.                                                                 |
| `404`       | `not_found`                    | The service does not exist for this broker account.                                                                                 |
| `429`       | `rate_limit_exceeded`          | The API key reached its rate limit. Check the `Retry-After` header.                                                                 |
| `500`       | `server_error`                 | The API could not create the request, queue the action, or complete internal processing.                                            |


## OpenAPI

````yaml api/openapi.yaml POST /v1/services/{service_number}/upgrade
openapi: 3.1.0
info:
  title: Broker API
  version: 1.0.0
  description: API for broker-scoped service, request, and report operations.
servers:
  - url: https://brokers.newyorkcityservers.com/api
    description: Broker Panel API
security:
  - bearerAuth: []
tags:
  - name: Authentication
  - name: Services
  - name: Requests
  - name: Reports
paths:
  /v1/services/{service_number}/upgrade:
    post:
      tags:
        - Services
      summary: Upgrade Service
      description: >-
        Submits a service plan upgrade for background processing. Requires
        `admin:full`.
      operationId: upgradeService
      parameters:
        - $ref: '#/components/parameters/ServiceNumber'
      requestBody:
        $ref: '#/components/requestBodies/PlanChangeRequest'
      responses:
        '200':
          description: Upgrade accepted for processing.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: '#/components/schemas/PlanChangeResult'
              example:
                success: true
                data:
                  request_id: REQ-002386
                  type: upgrade
                  request_status: accepted
                  service_number: 971100001
                  current_plan: Basic VPS
                  requested_plan: Standard VPS
                  submitted_date: '2026-06-21T15:00:00.000Z'
        '202':
          $ref: '#/components/responses/ReviewAccepted'
        '400':
          $ref: '#/components/responses/PlanChangeBadRequest'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/PermissionError'
        '404':
          $ref: '#/components/responses/ServiceNotFound'
        '429':
          $ref: '#/components/responses/RateLimitError'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    ServiceNumber:
      name: service_number
      in: path
      required: true
      description: Public service number parsed as a base-10 integer.
      schema:
        type: integer
        format: int64
  requestBodies:
    PlanChangeRequest:
      required: true
      content:
        application/json:
          schema:
            type: object
            required:
              - new_plan
            properties:
              new_plan:
                type: string
                description: >-
                  Target plan slug or label, accepted case-insensitively. Valid
                  slugs are basic-vps, standard-vps, professional-vps, and
                  dedicated-server.
          example:
            new_plan: standard-vps
  schemas:
    SuccessEnvelope:
      type: object
      required:
        - success
      properties:
        success:
          type: boolean
          const: true
        message:
          type: string
        pagination:
          $ref: '#/components/schemas/Pagination'
    PlanChangeResult:
      type: object
      required:
        - request_id
        - type
        - request_status
        - service_number
        - current_plan
        - requested_plan
        - submitted_date
      properties:
        request_id:
          type: string
        type:
          type: string
          enum:
            - upgrade
            - downgrade
        request_status:
          type: string
          const: accepted
        service_number:
          type: integer
        current_plan:
          type: string
        requested_plan:
          type: string
        submitted_date:
          type: string
          format: date-time
    Pagination:
      type: object
      required:
        - page
        - perPage
        - total
        - totalPages
      properties:
        page:
          type: integer
          minimum: 1
        perPage:
          type: integer
          minimum: 1
          maximum: 100
        total:
          type: integer
          minimum: 0
        totalPages:
          type: integer
          minimum: 0
    ReviewResult:
      type: object
      required:
        - request_id
        - request_status
        - message
      properties:
        request_id:
          type:
            - string
            - 'null'
        request_status:
          type: string
          enum:
            - pending
            - processing
            - nycservers_review
        message:
          type: string
        service_number:
          type:
            - integer
            - 'null'
        service_status:
          type: string
          const: pending
    ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          const: false
        error:
          $ref: '#/components/schemas/Error'
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
        details:
          type: object
          additionalProperties: true
  responses:
    ReviewAccepted:
      description: Request accepted for NYCServers review.
      content:
        application/json:
          schema:
            allOf:
              - $ref: '#/components/schemas/SuccessEnvelope'
              - type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/ReviewResult'
          example:
            success: true
            data:
              request_id: REQ-002386
              request_status: nycservers_review
              message: >-
                There was a setup issue. Your request has been escalated for
                NYCS review. No need to resubmit.
    PlanChangeBadRequest:
      description: >-
        Codes `invalid_parameter`, `invalid_request`, `missing_parameter`,
        `invalid_state`, or `service_pending_provisioning`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidPlan:
              value:
                success: false
                error:
                  code: invalid_parameter
                  message: Invalid plan
                  details:
                    valid_values:
                      - basic-vps
                      - standard-vps
                      - professional-vps
                      - dedicated-server
            pendingService:
              value:
                success: false
                error:
                  code: service_pending_provisioning
                  message: >-
                    Service is still pending provisioning and this action is not
                    available yet.
    AuthenticationError:
      description: >-
        Code `authentication_failed` for a missing, malformed, invalid,
        inactive, or expired API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: authentication_failed
              message: Invalid API key
    PermissionError:
      description: >-
        Code `insufficient_permissions` when the request IP is not whitelisted
        or a required scope is missing.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: insufficient_permissions
              message: IP address not whitelisted
    ServiceNotFound:
      description: Code `not_found` when no broker-owned service matches.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: not_found
              message: Service not found or access denied
    RateLimitError:
      description: Code `rate_limit_exceeded` when the API key exceeds its rate limit.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: rate_limit_exceeded
              message: Rate limit exceeded
    ServerError:
      description: >-
        Code `server_error` when authentication or internal processing cannot
        complete.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: server_error
              message: Internal server error
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: >-
        Send the API key in the Authorization bearer header. Production keys
        begin with `sk_live_`.

````