{
"openapi": "3.0.1",
"info": {
"title": "Authentication API",
"description": "Provides common authentication endpoints for ECI APIs.\n\nThis API enforces a rate limit of 100 requests per minute from the same Source IP. Other more specific rate limits may also apply.\n\nFAQs\n-----------------\n**Q:** How long is the access token valid?\\\n**A:** The token is valid for 60 minutes (3600 seconds). This duration is fixed.\n\n**Q:** Is there a refresh token available?\\\n**A:** No, there is no refresh token. The system uses the \"client_credentials\" OAuth2 grant type, which always requires the original clientId and secret to obtain a new access token.\n\n**Q:** How should the clientId and secret be stored?\\\n**A:** They should be stored securely. It is recommended to encrypt at least the secret at rest.\n\n**Q:** What is the recommended approach for handling token expiration?\\\n**A:** Cache the access token and use it until it is expired or nearly expired.\nThe caller can choose when to refresh: for example, 5 minutes before expiration, or after receiving a 401 response.\nIt's up to the caller's implementation strategy.\n\n**Q:** What happens when the access token is invalid or expired?\\\n**A:** You will receive a 401 Unauthorized response.\n\n**Q:** What is the best practice for handling 401 errors due to token expiration?\\\n**A:** Implement a retry handler that detects the 401 error, obtains a fresh token, and retries the failed call.\nEnsure the retry logic does not retry infinitely. Typically, no more than 3 attempts should be made before logging the failure.\nThis helps confirm whether the issue is truly related to authentication.",
"contact": {
"name": "ECI Manufacturing Integration Team",
"url": "https://www.ecisolutions.com/support/"
},
"version": "2.22.273+b02c1dfd00"
},
"servers": [
{
"url": "https://api-user.integrations.ecimanufacturing.com:443",
"description": "Production"
}
],
"paths": {
"/api/devices": {
"post": {
"tags": [
"AuthApi"
],
"summary": "Create Device",
"description": "This endpoint is used for device registraiton and activation. It is used by devices\r\nto initiate device activation by calling this endpoint and then displaying the activation\r\ncode to a user. \r\n
\r\nAn authenticated user then calls the PUT /devices/authorization endpoint\r\nwhich authorizes the activation of a device and provides data that will be\r\nsent back to the device waiting for action. It also optionally indicates\r\nthat a device credential should be created and issued to the waiting device.\r\n
\r\nThe device periodically calls GET /devices/{id}, waiting for isActivated\r\nto become true and to receive the properties and/or credentials generated.\r\n- Returns 201 when a device is created.
",
"operationId": "CreateDevice",
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceCreateModel"
}
]
}
},
"text/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceCreateModel"
}
]
}
},
"application/*+json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceCreateModel"
}
]
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/DeviceCreateResponse"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceCreateResponse"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/DeviceCreateResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/api/devices/{id}/activation": {
"post": {
"tags": [
"AuthApi"
],
"summary": "Activate Device",
"description": "Attempts to activate a device that has bene authorized for activation. Devices typically\r\npoll this endpoing periodically waiting for activation to complete.\r\n- \r\nReturns 200 OK when the device is activated.\r\n
- \r\nReturns 204 No Content when the device code has not yet been activated.\r\n
",
"operationId": "TryActivateDevice",
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceActivateRequestModel"
}
]
}
},
"text/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceActivateRequestModel"
}
]
}
},
"application/*+json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceActivateRequestModel"
}
]
}
}
}
},
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/DeviceActivatedResponse"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceActivatedResponse"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/DeviceActivatedResponse"
}
}
}
},
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/oauth2/api-user/token": {
"post": {
"tags": [
"AuthApi"
],
"summary": "Authenticate an API User via the OAuth 2.0 Client Credentials Grant/Flow.",
"description": "Accessible By: Everyone can use this api because it's Anonymous.\\\r\nAccessed From: Financial Integration.\\\r\nDescription:\r\n
\r\nThe API username and password must be provided in the client_id and client_secret parameters OR via the username/password values\r\nof an HTTP Basic Authentication header value.\r\n
\r\nThe scope value should be set to openid unless otherwise indicated.\r\n
\r\nThe grant_type value must be client_credentials.\r\n",
"operationId": "GetApiUserToken",
"parameters": [
{
"name": "authorization",
"in": "header",
"description": "You can provide the API username/password as an HTTP Basic authentication header or as a client_id and client_secret form encoded value",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"type": "object",
"properties": {
"client_id": {
"type": "string"
},
"client_secret": {
"type": "string"
},
"scope": {
"type": "string"
},
"grant_type": {
"type": "string"
}
}
},
"encoding": {
"client_id": {
"style": "form"
},
"client_secret": {
"style": "form"
},
"scope": {
"style": "form"
},
"grant_type": {
"style": "form"
}
}
},
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"client_id": {
"type": "string"
},
"client_secret": {
"type": "string"
},
"scope": {
"type": "string"
},
"grant_type": {
"type": "string"
}
}
},
"encoding": {
"client_id": {
"style": "form"
},
"client_secret": {
"style": "form"
},
"scope": {
"style": "form"
},
"grant_type": {
"style": "form"
}
}
}
}
},
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/OAuthAccessTokenResponse"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/OAuthAccessTokenResponse"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/OAuthAccessTokenResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"503": {
"description": "Server Error"
}
}
}
}
},
"components": {
"schemas": {
"DeviceActivateRequestModel": {
"required": [
"code"
],
"type": "object",
"properties": {
"code": {
"minLength": 1,
"type": "string"
}
},
"additionalProperties": false
},
"DeviceActivatedResponse": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The device unique ID",
"format": "uuid"
},
"isActivated": {
"type": "boolean",
"description": "Indicates if the device is activated"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Additional information provided by the activator",
"nullable": true
},
"credential": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceCredentialModel"
}
],
"description": "If the device activation requested an access token and refresh token\r\nfor the device, this property will contain the token information",
"nullable": true
}
},
"additionalProperties": false
},
"DeviceCreateModel": {
"required": [
"clientId"
],
"type": "object",
"properties": {
"clientId": {
"type": "string",
"description": "The client ID of the application registered to create devices.",
"format": "uuid"
},
"credentialType": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceCredentialType"
}
],
"description": "The requested type of credential to obtain along with the device\r\nregistration. This is not required and will default to None.",
"nullable": true
},
"description": {
"maxLength": 100,
"type": "string",
"description": "A description of the device to be displayed to the\r\nuser who will authorize activation of the device.",
"nullable": true
},
"origin": {
"maxLength": 250,
"type": "string",
"description": "The domain origin, if applicable, of the device.\r\nWill be displayed to the user who will authorize activation of the device.",
"nullable": true
},
"deviceType": {
"maxLength": 50,
"type": "string",
"description": "An application specific identifier for the type of device.\r\nWill be displayed to the user who will authorize activation of the device.",
"nullable": true
}
},
"additionalProperties": false
},
"DeviceCreateResponse": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "The device activation code to be displayed to the user",
"nullable": true
},
"id": {
"type": "string",
"description": "The device unique id",
"format": "uuid"
},
"codeExpires": {
"type": "string",
"description": "The expiration date/time of the activation code in UTC",
"format": "date-time",
"nullable": true
}
},
"additionalProperties": false
},
"DeviceCredentialModel": {
"type": "object",
"properties": {
"secret": {
"type": "string",
"description": "If requested, this will contain the secret that can be used\r\nto obtain tokens from the token_url using a resource-owner-password\r\ngrant.",
"nullable": true
},
"tokenEndpoint": {
"type": "string",
"description": "When a token is provided, this URL can be used with a refresh_token OAuth2 grant\r\nto obtain a new set of tokens.",
"nullable": true
},
"tokenIssuer": {
"type": "string",
"nullable": true
},
"tokenType": {
"type": "string",
"nullable": true
},
"accessToken": {
"type": "string",
"nullable": true
},
"idToken": {
"type": "string",
"nullable": true
},
"clientId": {
"type": "string",
"nullable": true
},
"expiresAt": {
"type": "integer",
"description": "The expiration date in unix epoch seconds.",
"format": "int64",
"nullable": true
},
"refreshToken": {
"type": "string",
"nullable": true
}
},
"additionalProperties": false
},
"DeviceCredentialType": {
"enum": [
"None",
"Token",
"Secret",
"TokenAndSecret"
],
"type": "string"
},
"OAuthAccessTokenResponse": {
"type": "object",
"properties": {
"access_token": {
"type": "string",
"nullable": true
},
"token_type": {
"type": "string",
"nullable": true
},
"expires_in": {
"type": "integer",
"format": "int32"
},
"refresh_token": {
"type": "string",
"nullable": true
}
},
"additionalProperties": false
},
"ProblemDetails": {
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"type": "integer",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"additionalProperties": { }
}
},
"securitySchemes": {
"oidc": {
"type": "openIdConnect",
"description": "Use id_token obtained from OpenID Connect flow.",
"openIdConnectUrl": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_9IYBf4TpD/.well-known/openid-configuration",
"x-tokenName": "id_token"
},
"Basic": {
"type": "http",
"description": "Username is ClientID, Password is Client Secret.",
"scheme": "Basic"
}
}
},
"security": [
{
"oidc": [
"openid"
]
},
{
"Basic": [ ]
}
]
}