# API versioning and lifecycle

The fulfillmenttools API is versionless. This means the API evolves in a backward-compatible way. The following changes are considered backward-compatible:

* Adding new API resources.
* Adding new optional request parameters to existing API methods.
* Adding new properties to existing API responses.
* Changing the order of properties in existing API responses.
* Adding values to enums (see [Enum handling](#enum-handling)).

All endpoints, fields, and types in the fulfillmenttools APIs have a lifecycle ranging from Alpha to Beta to General Availability (GA) and are marked as such. Additionally, fulfillmenttools may deprecate certain functionality in the API.

Consider the following example:

{% tabs %}
{% tab title="REST API" %}

```yaml
'/api/facilities/{facilityId}':
  get:
    operationId: getFacility
    summary: Get a facility with the given ID
    x-fft-api-lifecycle: ga
    responses:
      '200':
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Facility'

components:
  schemas:
    Facility:
      properties:
        id:
          type: string
          x-fft-api-lifecycle: ga
        description:
          type: string
          x-fft-api-lifecycle: alpha
```

In this case, the `facility` endpoint and entity are both GA. However, the `description` field is still under development and may change. When working with the `facility` endpoint, ensure that the information provided in the `description` field isn't integrated into any mission-critical components that might be sensitive to changes.
{% endtab %}

{% tab title="GraphQL API" %}
In GraphQL, lifecycle information is implemented via schema directives. Schema directives, except for `@deprecated`, aren't fetched during introspection. It's recommended to fetch the latest schema from the fulfillmenttools API manually.

```graphql
type Query {
  facility(id: String!): Facility @FFTMetadata(lifecycle = GA)
  listings: ListingConnection @FFTMetadata(lifecycle = GA)
}

type Facility @FFTMetadata(lifecycle = BETA) {
  id: ID! @FFTMetadata(lifecycle = GA)
  name: String! @FFTMetadata(lifecycle = GA)
  description: String! @FFTMetadata(lifecycle = ALPHA)

  listings: ListingConnection @semanticNonNull @FFTMetadata(lifecycle = BETA)
}

type ListingsConnection @FFTMetadata(lifecycle = GA) {
  edges: [ListingEdge] @semanticNonNull(levels = [0,1]) @FFTMetadata(lifecycle = GA)
}
```

The above example shows a typical case for mixed lifecycle flags in the fulfillmenttools GraphQL schema. Querying a facility and its `id` and `name` can be achieved using `GA` fields, which are fully covered under the fulfillmenttools SLAs. The same holds for listings, including filters like the `facilityRef` of the listing.&#x20;

However, querying all listings in a facility using `Facility.listings`, a non-GA field, isn't covered under the SLAs. However, the `description` field is still under development and may change. Ensure that the information provided in the `description` field isn't integrated into any mission-critical components that might be sensitive to changes.
{% endtab %}
{% endtabs %}

## Lifecycle overview

<table><thead><tr><th width="145.921875">Lifecycle state</th><th>Flag</th><th>Definition</th><th width="148">SLAs</th><th width="166">Breaking changes</th><th>Change notifications</th><th>Safe to use?</th></tr></thead><tbody><tr><td>Alpha</td><td>Yes</td><td>In early-stage development, it might not be fully functional, unavailable at times, and could be removed without warning.</td><td>No</td><td>Common (both semantic and syntactic)</td><td>No notifications.</td><td>Recommended to contact fulfillmenttools first.</td></tr><tr><td>Beta</td><td>Yes</td><td>In late-stage development available for public testing. Functionality exists, but is unavailable at times, and could be removed without warning.</td><td>No</td><td>Rare</td><td>No later than two weeks before breaking changes.</td><td>Recommended to contact fulfillmenttools first.</td></tr><tr><td>GA</td><td>No</td><td>Production-ready and stable.</td><td>Yes</td><td>No</td><td>// Does this mean yes?</td><td>Yes</td></tr><tr><td>Deprecated</td><td>Yes</td><td>Replaced by new endpoints. Only removed when its no longer in use.</td><td>Yes (if previously GA)</td><td>No (if previously GA)</td><td>// Does this mean yes?</td><td>It will still work, but you should use the recommended new endpoint.</td></tr></tbody></table>

## Enum handling

The fulfillmenttools schemas use many enums, for example, for status use. Adding a value to an enum is considered a nonbreaking change:

{% tabs %}
{% tab title="REST" %}

```diff
OrderStatus:
  type: "string"
  enum:
    - "OPEN"
    - "CANCELLED"
    - "LOCKED"
+   - "CLOSED"
```

{% endtab %}

{% tab title="GraphQL" %}

```diff
enum OrderStatus {
   OPEN
   CANCELLED
   LOCKED
+  CLOSED
}
```

{% endtab %}
{% endtabs %}

However, the tooling around this use of enumerations varies. A code generator will most likely produce enums that can't contain values different from the one described. When handling enums, the recommended practice is to map unknown enum values to recognized values or to values that yield an error.
