{
  "openapi": "3.0.4",
  "info": {
    "title": "Deep Blue Links API",
    "description": "Create, update and resolve your app's deep links from its servers and mobile apps. Every call sends the app's API key in the Api-Key header. An error answers its HTTP status with a JSON body: { \"message\": \"...\" }.",
    "version": "1.0"
  },
  "servers": [
    {
      "url": "https://dev.thedbl.ink"
    }
  ],
  "paths": {
    "/api/links": {
      "post": {
        "tags": [
          "Links"
        ],
        "summary": "Create a link",
        "description": "Creates a link in the app the API key belongs to, so `appId` must be that app. The path of `fullUrl` is kept and its host becomes the app's subdomain, and `shortUrl` uses one of the app's custom domains when `fullUrl` is on it. Leave `customShortCode` out to get a generated 8-character code, or send 1 to 64 characters without spaces or any of / ? # % \\; a code already in use answers 400. `title`, `description`, `imageUrl` and `fallbackUrl` are required but may be empty. Answers 400 once the organization's links for the month are used up. With the app's sandbox API key, which starts with `sandbox_`, the link is a sandbox link: the same kind of URL, counted like any link, and every response about it carries `isSandbox: true`. `isSandbox: true` with a live key answers 400.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinkRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinkRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/links/{id}": {
      "put": {
        "tags": [
          "Links"
        ],
        "summary": "Update a link",
        "description": "Replaces every field of one of the app's links, so `appId` must be the link's app. `fullUrl`, `shortUrl` and `customShortCode` follow the same rules as when creating a link. A link of another app answers 403. A sandbox key changes only sandbox links, so a live link answers 404 to it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLinkRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLinkRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      },
      "get": {
        "tags": [
          "Links"
        ],
        "summary": "Get a link",
        "description": "Returns one of the app's links and records the call as a click. A link of another app answers 404. A sandbox link's response carries `isSandbox: true`; other links' responses don't have the field.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Links"
        ],
        "summary": "Delete a link",
        "description": "Deletes one of the app's links for good, so its short URL stops working. A link of another app answers 403. A sandbox key deletes only sandbox links, so a live link answers 404 to it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/links/check-deferred": {
      "post": {
        "tags": [
          "Links"
        ],
        "summary": "Get the link that led to an install",
        "description": "Call it on the app's first launch after an install to get the link the user opened before installing. Send the device's IANA timezone, and on iOS also `device`: the screen's width and height in pixels (points times the screen scale) and the language. It answers with the link when it can tell which of the app's links the user opened in the hour before the launch, and 404 when it can't. On Android, read the `link` value from the Play install referrer and call `POST api/links/resolve` instead: that match is exact. A sandbox link's response carries `isSandbox: true`; other links' responses don't have the field.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MatchDeferredLinkRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/MatchDeferredLinkRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/MatchDeferredLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedLinkResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedLinkResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedLinkResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    },
    "/api/links/resolve": {
      "post": {
        "tags": [
          "Links"
        ],
        "summary": "Resolve the link that opened the app",
        "description": "Takes the URL that opened the app, either a universal link or app link or, on Android, the `link` value from the Play install referrer, and returns the link's `id`, `longUrl` and `shortUrl`. Records a click. A URL that isn't one of the app's links answers 404. A sandbox link's response carries `isSandbox: true`; other links' responses don't have the field.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveLinkRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveLinkRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedLinkResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedLinkResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResolvedLinkResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "CreateLinkRequest": {
        "required": [
          "appId",
          "description",
          "fallbackUrl",
          "fullUrl",
          "imageUrl",
          "title"
        ],
        "type": "object",
        "properties": {
          "appId": {
            "type": "integer",
            "format": "int32"
          },
          "fullUrl": {
            "minLength": 1,
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "fallbackUrl": {
            "type": "string"
          },
          "customShortCode": {
            "type": "string",
            "nullable": true
          },
          "isSandbox": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "DeviceRequest": {
        "required": [
          "language",
          "screenHeight",
          "screenWidth"
        ],
        "type": "object",
        "properties": {
          "screenWidth": {
            "maximum": 65535,
            "minimum": 1,
            "type": "number",
            "format": "double"
          },
          "screenHeight": {
            "maximum": 65535,
            "minimum": 1,
            "type": "number",
            "format": "double"
          },
          "language": {
            "maxLength": 64,
            "minLength": 0,
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "LinkResponse": {
        "type": "object",
        "properties": {
          "appId": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "fullUrl": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "fallbackUrl": {
            "type": "string",
            "nullable": true
          },
          "customShortCode": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "shortUrl": {
            "type": "string",
            "nullable": true
          },
          "iosBundleId": {
            "type": "string",
            "nullable": true
          },
          "androidPackageName": {
            "type": "string",
            "nullable": true
          },
          "isSandbox": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "MatchDeferredLinkRequest": {
        "required": [
          "timezone"
        ],
        "type": "object",
        "properties": {
          "timezone": {
            "minLength": 1,
            "type": "string"
          },
          "device": {
            "$ref": "#/components/schemas/DeviceRequest"
          }
        },
        "additionalProperties": false
      },
      "ResolveLinkRequest": {
        "required": [
          "url"
        ],
        "type": "object",
        "properties": {
          "url": {
            "minLength": 1,
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ResolvedLinkResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "longUrl": {
            "type": "string",
            "nullable": true
          },
          "shortUrl": {
            "type": "string",
            "nullable": true
          },
          "isSandbox": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "UpdateLinkRequest": {
        "required": [
          "appId",
          "description",
          "fallbackUrl",
          "fullUrl",
          "imageUrl",
          "title"
        ],
        "type": "object",
        "properties": {
          "appId": {
            "type": "integer",
            "format": "int32"
          },
          "fullUrl": {
            "minLength": 1,
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "fallbackUrl": {
            "type": "string"
          },
          "customShortCode": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "The app's API key",
        "name": "Api-Key",
        "in": "header"
      }
    }
  },
  "tags": [
    {
      "name": "Links"
    }
  ]
}