Kroger...

Documenting an API

Introduction

This document outlines the requirements for documenting a Kroger API.

All Kroger API documentation must meet both the requirements outlined in this document and the latest OpenAPI Specification (OAS). The following requirements are included in addition to those of OAS to:

  • Enhance the API documentation process.
  • Meet Kroger Architectural requirements.
  • Provide examples of Kroger use cases.
Some of the requirements of this document differ from those of OAS. You must meet the following requirements first, then use OAS for everything else.

Best practices are included in this document for additional guidance.

Document Conventions

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC2119.

Requirements


Contact Object

The contact object MUST include the following fields:

  • name
  • email
  • url

Example:

{
  "contact": {
    "name": "API Team",
	  "email": "digital-ipa@kroger.com",
	  "url": "confluence.com/ipa"
  }
}
contact: 
  name: API Team 
  email: digital-ipa@kroger.com
  url: confluence.com/ipa

OAS: Contact Object

Data Types

Data Types MUST comply with the following formats.

Additional Format Examples:

date-time used for representing time only:

{
  "createTime": {
    "type": "date-time",
    "example": "16:05:05"
  }
}
createdTime:
  type: date-time
  example: 16:05:05

address:

{
  "location": {
    "address": {
      "properties": {
        "addressLine1": {
          "example": "2900 W. St. Rt. 22 & 3",
          "type": "string"
        },
        "addressLine2": {
          "type": "string"
        },
        "locality": {
          "example": "Maineville",
          "type": "string",
        },
        "USCounty": {
          "example": "WARREN COUNTY",
          "type": "string"
        },
        "region": {
          "example": "OH",
          "type": "string"
        },
        "postalCode": {
          "example": "45039",
          "type": "string"
        }
      },
      "type": "string"
    }
  }
}
locations:
  address:
    properties:
      addressLine1:
        example: 2900 W. St. Rt. 22 & 3
        type: string
      addressLine2: 
        type: string
      locality:
        example: Maineville
        type: string
      USCounty:
        example: WARREN COUNTY
        type: string
      region:
        example: OH
        type: string
      postalCode:
        example: 45039
        type: string
    type: object

geoLocation:

{
  "location": {
    "geoLocation": {
      "properties": {
        "latLng": {
          "example": "39.3110881,-84.2751167",
          "type": "string"
        },
        "latitude": {
          "example": "39.3110881",
          "type": "number"
        },
        "longitude": {
          "example": "-84.2751167",
          "type": "number"
        }
      }, 
      "type": "object"
    }
  }
}
locations:
  geoLocation:
    properties:
      latLng:
        example: 39.3110881,-84.2751167
        type: string
      latitude:
        example: 39.3110881
        type: number
      longitude:
        example: -84.2751167
        type: number
    type: object

currency:

{
  "price": "USD 45.34"
}
price: USD 45.34

Unit of Measurements:

{
  "dimension": {
    "height": "5.5 [ft_i]",
    "width": "3.5 [ft_i]"
  }
}
dimensions:
  height: 5.5 [ft_i]
  width: 3.5 [ft_i]

OAS: Data Types

Document Structure

The root OpenAPI document MUST follow either the openapi.json or openapi.yaml naming convention.

OAS: Document Structure

External Documentation Object

The external documentation object MUST include the following fields:

  • description
  • url

External documentation can be any relevant materials outside of your API documentation.

Example:

{
  "externalDocs": {
	  "description": "Find more info here",
	  "url": "https://developer.kroger.com/documentation/coupon"
  }
}
externalDocs:
  description: Find more info here
  url: https://developer.kroger.com/documentation/coupon

OAS: External Documentation Object

Format

Best Practice

It is NOT RECOMMENDED to mix formats in a single API document.

OAS: Format

Info Object

The info object MUST include the following fields:

{
  "info": {
	  "title": "The Kroger Co.",
	  "description": "A set of APIs have been made available for applications to integrate with The Kroger Co. family of stores data.",
	  "termsOfService": "https://developer.kroger.com/terms",
	  "contact": {
	    "name": "Digital IPA",
	    "email": "digitalipa@kroger.com",
	    "url": "confluence.com/ipa"
	  },
	  "license": {
      "name": "LICENSED",
      "url": "https://developer.kroger.com/license"
    },
	  "version": "1.0.0"
  }
}
info: 
  title: "The Kroger Co."
  description: "A set of APIs have been made available for applications to integrate with The Kroger Co. family of stores data."
  termsOfService: https://developer.kroger.com/terms
  contact: 
    name: "Digital IPA"
    email: "digitalipa@kroger.com"
    url: "confluence.com/ipa"
  license: 
    name: LICENSED
    url: https://developer.kroger.com/license
  version: "1.0.0"

OAS: Info Object

License Object

The license object MUST include the following fields:

Example:

{
  "license": {
      "name": "LICENSED",
      "url": "https://developer.kroger.com/license"
  }
}
license: 
  name: LICENSED
  url: https://developer.kroger.com/license

OAS: License Object

Media Type Object

Media type examples MUST be included in your API documentation.

OAS: Media Type Object

OAuth Flow Object

The OAuth2 flow object MUST include the following fields when applicable:

Field Applies to
authorizationUrl OAuth2 ("authorizationCode")
tokenUrl OAuth2 ("password", "clientCredentials", "authorizationCode")
refreshUrl OAuth2
scopes OAuth2

Scopes MUST use the following format:

urn : top-level domain : organization : API product : domain : function : level of access

See the following table for individual scope format details.

Namespace Example Description
Uniform Resource Name urn A URI that defines something’s identity but does not provide a location to access the item. See Uniform Resource Names (RFC8141).
Top-level Domain com Defines the purpose of the organization.
Organization kroger The organization affiliated with the scope.
API Product commerce The product area the domain is associated with.
Domain coupon A specified sphere of activity or knowledge.
Function personalization The specific function that is more granular than the domain access. Note: this field is not required if not needed.
Level of access read Either read or write access to a domain. Read and write MUST be spelled out.

Example:

{
  "type": "oauth2",
  "flows": {
    "authorizationUrl": "https://api.kroger.com/v1/connect/oauth2/authorize",
    "scopes": {
      "urn:com:kroger:commerce:coupon:personalization:write": "update personalized products",
      "urn:com:kroger:commerce:coupon:coupon:read": "view current coupons"
      }
    },
    "authorizationCode": {
      "authorizationUrl": "https://api.kroger.com/v1/connect/oauth2/authorize",
      "tokenUrl": "https://api.kroger.com/v1/connect/oauth2/token",
      "refreshUrl": "https://api.kroger.com/v1/identity-provider/connect/oauth2/token",
      "scopes": {
        "urn:com:kroger:commerce:coupon:personalization:write": "update personalized products",
        "urn:com:kroger:commerce:coupon:coupon:read": "view current coupons"
      }
   }
}
type: oauth2
flows: 
 authorizationUrl: "https://api.kroger.com/v1/connect/oauth2/authorize"
 scopes: 
  "urn:com:kroger:commerce:coupon:personalization:write": "update personalized products"
  "urn:com:kroger:commerce:coupon:coupon:read": "view current coupons"
authorizationCode: 
 authorizationUrl: "https://api.kroger.com/v1/connect/oauth2/authorize"
 tokenUrl: "https://api.kroger.com/v1/connect/oauth2/token"
 refreshURl: "https://api.kroger.com/v1/identity-provider/connect/oauth2/token"
 scopes: 
  "urn:com:kroger:commerce:coupon:personalization:write": "update personalized products"
  "urn:com:kroger:commerce:coupon:coupon:read": "view current coupons"

OAS: OAuth Flow Object

OAuth Flows Object

The OAuth2 flows object MUST include the following fields:

  • authorizationCode
  • clientCredentials
  • password

The OAuth2 implicit flow is not supported and MUST NOT be used.

OAS: OAuth Flows Object

OpenAPI Object

The OpenAPI object MUST include the following fields:

OAS: OpenAPI Object

Paths Object

If you have more than one of the same operation for a resource, each operations MUST be its own path due to the path parameter restrictions of OAS.

Example:

{
	"paths": {
		"/products/": {
			"get": {
				"summary": "Product List",
				"description": "Returns a full list of products.",
				"operationId": "productGet",
				"responses": {
					"200": {
						"description": "OK"
					}
				}
			}
		},
		"/products/{id}": {
			"get": {
				"summary": "Product by ID",
				"description": "Returns a single product by ID.",
				"operationId": "productGetID",
				"parameters": [
					{
						"in": "path",
						"name": "id",
						"required": true,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "OK"
					}
				}
			}
		},
		"/products/{id1,id2,id3,...}": {
			"get": {
				"summary": "Products by IDs",
				"description": "Returns multiple products by ID.",
				"operationId": "productsGetIDs",
				"parameters": [
					{
						"in": "path",
						"name": "id1,id2,id3,...",
						"required": true,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "OK"
					}
				}
			}
		}
	}
}
paths:
  /products/:
    get:
      summary: Product List
      description: Returns a full list of products.
      operationId: "productGet"
      responses:
        '200':
          description: OK
  /products/{id}:
    get:
      summary: Product by ID
      description: Returns a single product by ID. 
      operationId: "productGetID"
      parameters:
      - in: path
        name: "id"
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
  /products/{id1,id2,id3,...}:
    get:
      summary: Products by IDs
      description: Returns multiple products by ID. 
      operationId: "productsGetIDs"
      parameters:
      - in: path
        name: "id1,id2,id3,..."
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK

OAS: Paths Object

Reference Object

Best Practice

The reference object should use the following format:

"$ref": "#/components/schemas/model"

OAS: Reference Object

Responses Object

There MUST be an example for every supported HTTP status code.

OAS: Responses Object

Security Filtering

There MUST NOT be any API documentation omitted that is required by OAS. Any restrictions to documentation are handled by the marketplace team during the ingestion process.

OAS: Responses Object

Security Requirement Object

The {name} field MUST containing either HTTP or OAuth as the value.

Example:

{
	"security": {
		"User Context": [
			"urn:com:kroger:commerce:coupon:personalization:write", 
			"urn:com:kroger:commerce:coupon:coupon:read"
		]
	}
}
security: 
  User Context: 
    - urn:com:kroger:commerce:coupon:personalization:write, 
    - urn:com:kroger:commerce:coupon:coupon:read

OAS: Security Requirement Object

Security Scheme Object

This section is only required for services behind the gateway that MUST use the OAuth2 framework.

The security scheme object MUST include the following fields when applicable:

Field Applies to
type All
name API key
in API key
scheme HTTP
flows OAuth2
OpenIdConnectURL is not supported and therefor the field MUST be left blank.

OAuth2 Example:

{
  "type": "oauth2",
  "flows": {
    "password": {
      "authorizationUrl": "https://api.kroger.com/v1/connect/oauth2/token",
      "scopes": {
        "urn:com:kroger:commerce:coupon:personalization:write": "update personalized products",
        "urn:com:kroger:commerce:coupon:coupon:read": "view current coupons"
      }
    }
  }
}
type: oauth2
flows: 
 password: 
  authorizationUrl: "https://api.kroger.com/v1/connect/oauth2/token"
  scopes: 
   "urn:com:kroger:commerce:coupon:personalization:write": "update personalized products"
   "urn:com:kroger:commerce:coupon:coupon:read": "view current coupons"

HTTPS Example:

{
  "type": "https",
  "scheme": "basic"
}
type: https
scheme: basic

OAS: Security Scheme Object

Specification Extensions

The follow Vendor Extensions are available for use:

Extension Type Description
x-tagGroups Tag Group Object A list of tag groups.
x-ignoredHeaderParameters string A list of ignored headers.
x-traitTag boolean In Swagger two operations can have multiple tags. This property distinguishes between tags that are used to group operations (default) from tags that are used to mark operation with certain trait (true value).
x-displayName string Defines the text that is used for this tag in the menu and in section headings.
x-code-sample Code Sample Object A list of code samples associated with operation.
x-extendedDiscriminator string Specifies extended discriminator for use in polymorphism and inheritance.

Examples:

x-tagGroup

{
  "x-tagGroups": [
    {
      "name": "Stores",
      "tags": ["locations", "products", "carts"]
    },
  ]
}
x-tagGroup:
  - name: Stores
    tags:
      - locations
      - products
      - carts

X-ignoreHeaderParameter

{
  "OpenAPI": "3.0",
  "info": {
      ...
  },
  "tags": [...],
  "x-ignoredHeaderParameters": [
    "filter.term",
	"filter.brand",
	"filter.fulfillment"
  ]
}
OpenAPI: '3.0'
info:
  ...
tags: [...]
x-ignoredHeaderParameters:
  - filter.term
  - filter.brand
  - filter.fulfillment

x-traitTag

{
    "name": "Pagination",
    "description": "Pagination description (can use markdown syntax)",
    "x-traitTag": true
}
name: Pagination
description: Pagination description (can use markdown syntax)
x-traitTag: true

x-code-sample

{
  "lang": "JavaScript",
  "source": "console.log('Hello World');"
}
lang: JavaScript
source: console.log('Hello World');

OAS: Specification Extensions

Tag Object

Projections MUST be documented as a group of operations using the tag object. Projections MUST also be documented as a query parameter for each operation. The query parameter MUST be a string that references the projection tag in the description.

Example:

{
  "tags": [
    {
      "name": "products",
      "description": "Enterprise representation of products\n\n ---\n\n**Projection Format:** \"products[inventories.compact,images.compact,nutrition[certifications.compact],prices.compact]\"\n        \n        \n**Available choices**\n  * products\n    * inventories  [**full** | **compact**]\n    * images  [**full** | **compact**]\n    * nutrition  \n        * certifications [**full** | **compact**]\n    * prices [**full** | **compact**]"
    },
    {
      "name": "products & coupons",
      "description": "Enterprise representation of products\n\n ---\n\n**Projection Format:** \"products[inventories.compact,images.compact,nutrition[certifications.compact],prices.compact]\"\n        \n        \n**Available choices**\n  * products\n    * inventories  [**full** | **compact**]\n    * images  [**full** | **compact**]\n    * nutrition  \n        * certifications [**full** | **compact**]\n    * prices [**full** | **compact**]\n\n\n---\n      \n**Projection Format:** \"coupons.compact\"\n      \n      \n**Available choices**\n  * coupons [**full** | **compact**]"
    }
  ],
  "paths": {
    "/products-composite": {
      "get": {
        "tags": [
          "products"
        ],
        "summary": "Get Products List",
        "description": "This query is a representation for product(s) based on filter terms.",
        "operationId": "productByID",
        "parameters": [
          {
            "name": "projection",
            "in": "query",
            "description": "This defines the desired shape of the response object.  <br> See: [Available Projections](http://developer.kroger.com/reference#tag/products)",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/productsWithCoupons": {
      "get": {
        "tags": [
          "products & coupons"
        ],
        "summary": "Get Products List with Coupons",
        "description": "This query is a representation for product(s) & associated coupon(s) based on filter terms.",
        "operationId": "productwithcoupon",
        "parameters": [
          {
            "name": "projection",
            "in": "query",
            "description": "This defines the desired shape of the response object.  <br> See: [Available Projections](http://developer.kroger.com/reference#tag/products%20%26%20coupons)",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  }
}
tags:
  - name: "products"
    description: >-
      Enterprise representation of products
  
       ---
      
      **Projection Format:** "products[inventories.compact,images.compact,nutrition[certifications.compact],prices.compact]"
              
              
      **Available choices**
        * products
          * inventories  [**full** | **compact**]
          * images  [**full** | **compact**]
          * nutrition  
              * certifications [**full** | **compact**]
          * prices [**full** | **compact**]
  - name: "products & coupons"
    description: >-
      Enterprise representation of products
  
       ---
      
      **Projection Format:** "products[inventories.compact,images.compact,nutrition[certifications.compact],prices.compact]"
              
              
      **Available choices**
        * products
          * inventories  [**full** | **compact**]
          * images  [**full** | **compact**]
          * nutrition  
              * certifications [**full** | **compact**]
          * prices [**full** | **compact**]
      
      
      ---
            
      **Projection Format:** "coupons.compact"
            
            
      **Available choices**
        * coupons [**full** | **compact**]
paths:
  /products-composite:
    get:
      tags:
        - "products"
      summary: "Get Products List"
      description: "This query is a representation for product(s) based on filter terms."
      operationId: "productByID"
      parameters:
        - name: projection
          in: query
          description: >-
            This defines the desired shape of the response object. 
            <br>
            See: [Available Projections](http://developer.kroger.com/reference#tag/products)
          required: false
          schema:
            type: string
      responses:
        200:
          description: OK
  /productsWithCoupons:
    get:
      tags:
        - "products & coupons"
      summary: "Get Products List with Coupons"
      description: "This query is a representation for product(s) & associated coupon(s) based on filter terms."
      operationId: "productwithcoupon"
      parameters:
        - name: projection
          in: query
          description: >-
            This defines the desired shape of the response object. 
            <br>
            See: [Available Projections](http://developer.kroger.com/reference#tag/products%20%26%20coupons)
          required: false
          schema:
            type: array
            items:
              type: string
      responses:
        200:
          description: OK