# Dentbird OpenAPI Documentation

## --- Dentbird Open API ---

&#x20; Dentbird provides an OpenAPI using an [Oauth2.0](https://oauth.net/2/)-based user authentication method. It supports [OpenID-Connect](https://openid.net/developers/how-connect-works/) and allows users to obtain tokens based on jwt for users through the `Authorization Code` method.

&#x20; OpenAPI calls are made using an `Access Token`, and an `Access Token` can be issued using a `Refresh Token`.

### Authentication

The [`Authorization Code`](https://oauth.net/2/grant-types/authorization-code/) is a method used to obtain access rights to the user's resources. This method involves the client obtaining an `authorization code` with the approval of the resource owner and obtaining an `access token` through it.

#### Refresh Token

It's a RefreshToken that distinguishes users.

#### **Access Token**

It's a Token that distinguishes users. When calling OpenAPI, it should be included as the following Bearer Token

#### Authentication Process

1. The client redirects the user to the authorization server's approval endpoint.
2. The user approves access rights for the client.
3. The authentication server redirects the user to the client's redirect URI, including an authentication code.
4. The client requests an access token from the authentication server using the authentication code.&#x20;
5. The authentication server issues an access token to the client.

### PKCE

[PKCE](https://oauth.net/2/pkce/) is a method to prevent attackers from intercepting the `authentication code` and obtaining an `access token`. The client creates a `code challenge` value and requests an `authorization code` using this value. When requesting an `access token` using the `authorization code`, the `code verifier` value is submitted together to verify the validity of the request by the authentication server.

#### **Format**

The `code_verifier` is composed of a high-entropy cryptographic random string using the characters `[A-Z]` / `[a-z]` / `[0-9]` / `-` / `.` / `_` / `.` The minimum length is 43 characters, and the maximum length is 128 characters.

```
code-verifier = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39
```

#### **How it Works**

1. **Creation of code verifier**: The client first generates a random string called the code challenge (`code_verifier`).

```
code_verifier = random_string_of_43_128_chars() // YtMo4nSIaf5ggWTQfh4xNRtH7PfQ1kB9LXxhIQjFna
```

2. **Conversion to code\_challenge**: The client takes the generated `code_challenge`, hashes it with SHA256, and then Base64 URL encodes it to produce the `code_challenge`. This transformation method is referred to as S256.

```
code_challenge = BASE64URL-ENCODE(SHA256(code_verifier)) // NwM8WVZwSBtkw--lw3u7WrOgHEA9vD1IaM-uTDm2XHg
```

3. **Request for Authorization Code**: The client requests the authorization code, including the `code_challenge`. At this time, the transformation method (S256) is passed as the `code_challenge_method` parameter.

```http
GET /oidc/auth
?response_type=code
&client_id=foo
&redirect_uri=https://client.example.com/callback
&scope=openid user
&code_challenge=NwM8WVZwSBtkw--lw3u7WrOgHEA9vD1IaM-uTDm2XHg
&code_challenge_method=S256
```

4. **Request for Access Token**: After receiving the authorization code, the client sends the original `code_verifier` when requesting the access token.
5. **Verification**: The authentication server recalculates the `code_challenge` using the provided `code_verifier` from the client and checks if it matches the `code_challenge` stored in the previous step. If they match, the access token is issued.

```http
POST oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTH_CODE
&redirect_uri=https://client.example.com/callback
&client_id=foo
&client_secret=bar
&code_verifier=YtMo4nSIaf5ggWTQfh4xNRtH7PfQ1kB9LXxhIQjFna

```

### state

The `state` parameter is used to prevent [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) attacks. The client sends a random value as the `state` parameter during the authentication request, and the authentication server returns this value as is. The client verifies the returned value to confirm the validity of the request.

### nonce

`nonce` is used to prevent [replay attacks](https://en.wikipedia.org/wiki/Replay_attack). The client sends a random value as the `nonce` parameter during the authentication request, and the authentication server includes this value in the ID token when returning it. The client verifies the `nonce` value of the returned ID token to confirm the validity of the request.

### OpenID Connect

`OpenID Connect` is a user authentication protocol that extends `OAuth 2.0`. Through `OIDC`, clients can securely obtain a user's authentication status and basic profile information.

#### ID Token

The most important element in `OIDC` is the `ID token`. The `ID token` is provided in `JWT (JSON Web Token)` format and contains the user's authentication and profile information.

## Authentication Process

#### Login and Authorize approve process

1. Clicking on the authentication link will take the end user to the Dentbird OpenAPI Log In page\
   ![](https://1510404440-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPNfAeLceFdKIdLyjkIAe%2Fuploads%2FseA1VMiMFN31q7Z2oRLG%2Fimage.png?alt=media\&token=0918254a-d2fe-4c46-bd71-3726e77a0048)
2. After entering their Dentbird ID credentials and logging in, the user will be redirected to the OAuth consent page.\
   ![](https://1510404440-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPNfAeLceFdKIdLyjkIAe%2Fuploads%2Fn6MhOMucj4mdoUsusAnT%2Fimage.png?alt=media\&token=c3be7b46-66fa-4c24-8161-1a20328e31c7)
3. When consent has been granted, the user will be redirected back to your callback URL (redirect\_uri) with an additional query parameter that contains the authorization code, iss, and state.

### Authorization Code Issuance

```
GET /oidc/auth
```

#### Request Query Parameters

<table><thead><tr><th width="235.33333333333331">Parameter</th><th width="147">Required</th><th>Description</th><th data-hidden>Description</th></tr></thead><tbody><tr><td>client_id</td><td>required</td><td>Client unique identifier</td><td>Client unique identifier</td></tr><tr><td>redirect_uri</td><td>required</td><td>URL to which the user will be redirected after authentication</td><td>URL to which the user will be redirected after authentication</td></tr><tr><td>scope</td><td>required</td><td>Agree items to request consent from the user</td><td>Agree items to request consent from the user</td></tr><tr><td>response_type</td><td>required</td><td><code>code</code> (to use authorization code method)</td><td>Fixed with <code>code</code> to use authorization code method</td></tr><tr><td>code_challenge</td><td>required</td><td><code>PKCE(Proof Key for Code Exchange)</code> is used to protect authorization codes</td><td><code>PKCE(Proof Key for Code Exchange)</code> is used to protect authorization codes.</td></tr><tr><td>code_challenge_method</td><td>required</td><td><code>S256</code> (Method used to encode code_verifier for code_challenge parameter)</td><td>Method used to encode <code>code_verifier</code> for <code>code_challenge</code> parameter. Secure with <code>S256</code></td></tr><tr><td>response_mode</td><td>optional</td><td>Determine the format of the result (e.g., <code>query</code>, <code>fragment</code>, <code>form_post</code>)<br><a data-mention href="#response_mode">#response_mode</a></td><td>Determine the format of the result (e.g., query, fragment, form_post)</td></tr><tr><td>state</td><td>optional</td><td>The client sends an arbitrary value to the <code>state</code> parameter upon authentication request, which the authentication server returns. The client validates the returned value to validate the request.</td><td>The client sends an arbitrary value to the <code>state</code> parameter upon authentication request, which the authentication server returns. The client validates the returned value to validate the request.</td></tr><tr><td>nonce</td><td>optional</td><td>Included in ID tokens issued through <code>OpenId Connect</code> (requested only if OIDC is used)</td><td>Included in ID tokens issued through <a data-mention href="#openid-connect">#openid-connect</a>requested only if OIDC is used)</td></tr></tbody></table>

#### Response

The response to the request for the authorization code is redirected with HTTP 303 and is delivered to the `redirect uri` via a `GET` request. Information such as code, iss, etc. is passed as query parameters.

<table><thead><tr><th width="211">Parameter</th><th width="147.33333333333331">Required</th><th>Description</th><th data-hidden>Description</th></tr></thead><tbody><tr><td>code</td><td>required</td><td><code>Authorization code</code> for issuing tokens</td><td>Authorization code for issuing tokens</td></tr><tr><td>iss</td><td>required</td><td>Token Issuer</td><td>Token Issuer</td></tr><tr><td>state</td><td>optional</td><td>Same value as the state value delivered on request</td><td>Same value as the <code>state</code> value delivered on request</td></tr></tbody></table>

#### Example

\<Request>

```
GET /oidc/auth?client_id=foo
&redirect_uri=${REDIRECT_URI}
&scope=${SCOPE}
&response_type=code
&response_mode=query
&code_challenge_method=S256
&code_challenge=${CODE_CHALLENGE}
&state=${STATE}
&nonce=${NONCE}
```

\<Response>

{% code overflow="wrap" %}

```http
HTTP 303 Location: ${REDIRECT_URI}?code=${AUTHORIZE_CODE}&iss=https://dentbird.com
```

{% endcode %}

### Token Issuance

```
POST /oidc/token
```

{% hint style="info" %}
[#reasons-to-request-tokens-from-the-server](#reasons-to-request-tokens-from-the-server "mention")
{% endhint %}

#### Request header

| Key          | Value                             |
| ------------ | --------------------------------- |
| Content-Type | application/x-www-form-urlencoded |

#### Request body form

<table><thead><tr><th width="219">Parameter</th><th width="147.33333333333331">Required</th><th>Description</th><th data-hidden>Description</th></tr></thead><tbody><tr><td>client_id</td><td>required</td><td>Client unique identifier</td><td>Client unique identifier</td></tr><tr><td>client_secret</td><td>required</td><td>Password for client</td><td>Password for client</td></tr><tr><td>code</td><td>required</td><td><code>Authorization code</code> obtained by issuing authorization code</td><td><code>Authorization code</code> obtained by issuing authorization code</td></tr><tr><td>grant_type</td><td>required</td><td><code>authorization_code</code> (to use authorization code method)</td><td><code>authorization_code</code></td></tr><tr><td>redirect_uri</td><td>required</td><td>URL to which the user will be redirected after authentication</td><td>URL to which the user will be redirected after authentication</td></tr><tr><td>code_verifier</td><td>required</td><td>Same <code>code verifier</code> used to get <code>authorization code</code>. Required if <code>PKCE</code> is used for authentication code assignment requests</td><td>Same <code>code verifier</code> used to get <code>authorization_code</code>. Required if <code>PKCE</code> is used for authentication code assignment requests</td></tr><tr><td>reponse_type</td><td>required</td><td><code>code</code></td><td><code>code</code></td></tr></tbody></table>

\<Example>

```http
POST /oidc/token
Content-Type: application/x-www-form-urlencoded

code=TTgAxy9gCCOES28ZOSdah41Oi36NixtvdyY4UFtqRU3
&client_id=foo
&client_secret=bar
&grant_type=authorization_code
&redirect_uri=https://oauthdebugger.com/debug
&code_verifier=gOWfDZUsAR4sFMFIdf76hEgzTrWrsCql3wlqTtsjFZV
&reponse_type=token
```

#### Response

#### \<Body>

<table><thead><tr><th width="196">Parameter</th><th width="142.33333333333331">Required</th><th>Description</th><th data-hidden>Description</th></tr></thead><tbody><tr><td>access_token</td><td>required</td><td>Requested Access Token</td><td>Requested Access Token</td></tr><tr><td>expires_in</td><td>required</td><td>Expiration date of access_token</td><td>Expiration date of <code>access token</code></td></tr><tr><td>refresh_token</td><td>required</td><td>After the <code>access token</code> expires, you can use it to obtain other <code>access tokens</code>.</td><td>After the <code>access token</code> expires, you can use it to obtain other <code>access tokens</code>.</td></tr><tr><td>id_token</td><td>optional</td><td>ID token issued through <code>OpenIDConnect</code> extensions, including <code>Base64</code> encoded user credentials (including nonce)</td><td><code>ID token</code> issued through <a data-mention href="#openid-connect">#openid-connect</a>extensions, including <code>Base64</code> encoded user credentials (including <code>nonce</code>)</td></tr><tr><td>scope</td><td>required</td><td>Agree items to request consent from the user</td><td>Agree items to request consent from the user</td></tr><tr><td>token_type</td><td>required</td><td><code>Bearer</code></td><td>Type of token</td></tr></tbody></table>

\<Example>

```http
200 OK
Content-Type: application/json;charset=UTF-8

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImF0K2p3dCJ9.eyJqdGkiOiJVdmhHcG5GV2ppaGlUbC1OczNOQUoiLCJzdWIiOiI2NDgxOTkyMzg1YWEzM2RkYWUxM2FkMTkiLCJpYXQiOjE2OTI2NzIzMTQsImV4cCI6MTY5MjY3MjkxNCwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBjYXNlIiwiY2xpZW50X2lkIjoiZm9vIiwiaXNzIjoiaHR0cHM6Ly9kZXYtb3Blbi1hcGktc2VydmVyLmRlbnRiaXJkLmNvbSIsImF1ZCI6ImZvbyJ9.qEG3Cl7RLmZbi3Mfo4SAd1HbCUmnbW-F_ZfAb59jGX0",
  "expires_in": 3600,
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InIxTGtiQm8zOTI1UmIyWkZGckt5VTNNVmV4OVQyODE3S3gwdmJpNmlfS2MifQ.eyJub25jZSI6ImZ4M3dhZWR0cXdmIiwiYXRfaGFzaCI6ImZ2QkpXZW15WmtDckVFTVE5V05GdXciLCJhdWQiOiJmb28iLCJleHAiOjE2OTI2NzU5MTQsImlhdCI6MTY5MjY3MjMxNCwiaXNzIjoiaHR0cHM6Ly9kZXYtb3Blbi1hcGktc2VydmVyLmRlbnRiaXJkLmNvbSJ9.KLVI7p5Ca3OtAyhPqs8mP0CMukg6y_XbZ3sUGJt5P-i5LoXT7Ummz6uvzDKPVcDSOjN62MlkoOn7VhzXCgcZaCWeR2u_e94wO9n2_LYosvBvdfqX449PoXKd4amhfZhd6Kx6exFBRkS_enoQYtGFiJJjo_ZipSsckzoFeatIs5J1EeJSdh4XfX3gxqwHSSEmerlDOCrSC_6viLhA8cQbT_YSUMQNpGqKuFluEoNZV4uJAPfUnab7UiK3OfETfHS4WRqbdJHIhDdzNBX4wiFlEWS8Np7l0puwEFA9xRf_h6X_7C5DCDcFMsYsKB1nq56CzaGqWd7nJaB-ZzFjjCtoRg",
  "refresh_token": "MiecFsBXRJQzU3V5WKo5aFGY2YVlBFPqsmTP7q5KoRu",
  "scope": "openid user design-case file",
  "token_type": "Bearer"
}
```

### Tokens

#### ID Token

* `nonce` : The nonce value passed by the client during the authentication request
* `aud` : Token target (client ID)
* `exp` : Token expiration time
* `iat` : Token issuance time
* `iss` : Token issuer

```json
{
  "nonce": "db7412d23xe",
  "aud": "foo",
  "exp": 1695704543,
  "iat": 1695700943,
  "iss": "https://dentbird.com"
}
```

#### Access Token

The Access Token is a token used by the client to access the resource server. This token represents the permissions granted by the user to the client. You can request the Resource Server ([https://open-api.dentbird.com](https://open-api.dev-dentbird.com/)) using the issued

* `jti` : Unique token identifier
* `sub` : Unique identifier of the user
* `iat` : Token issuance time
* `exp` : Token expiration time
* `scope` : List of approved permissions
* `client_id` : Client ID
* `iss` : Token issuer
* `aud` : Token target (client ID)

```json
{
  "jti": "Ee69NBWduf3_G4_MypSr7",
  "sub": "64dc7e2829ecb4004dc88a5b",
  "iat": 1695608412,
  "exp": 1695694812,
  "scope": "openid user design-case file",
  "client_id": "foo",
  "iss": "https://auth-server.dev-dentbird.com",
  "aud": "foo"
}
```

#### Refresh Token

The `Refresh Token` is a token used to obtain a new `Access Token` when the `Access Token` has expired

### Token Reissue

`OAuth 2.0` provides a mechanism for users to obtain a new `access token` without going through the entire authentication process again. This is achieved using the `refresh token`.

```
POST /oidc/token
```

#### Request header

| Key          | Value                             |
| ------------ | --------------------------------- |
| Content-Type | application/x-www-form-urlencoded |

#### Request body form

| Parameter      | Description                                  | Required |
| -------------- | -------------------------------------------- | -------- |
| client\_id     | Client unique identifier                     | required |
| client\_secret | Password for client                          | required |
| grant\_type    | `refresh_token`                              | required |
| refresh\_token | refresh token issued                         | required |
| scope          | Agree items to request consent from the user | required |

\<Example>

```http
POST /oidc/token
Content-Type: application/x-www-form-urlencoded

client_id=foo
&client_secret=bar
&grant_type=refresh_token
&refresh_token=18L9kQXGc5dPpvEtjN90lmHQxCzU4JeRiHTnKcPqJgM
&scope=openid user file design-case
```

\<Response>

\<Body>

<table><thead><tr><th width="196">Parameter</th><th width="142.33333333333331">Required</th><th>Description</th><th data-hidden>Description</th></tr></thead><tbody><tr><td>access_token</td><td>required</td><td>Requested Access Token</td><td>Requested Access Token</td></tr><tr><td>expires_in</td><td>required</td><td>Expiration date of access_token</td><td>Expiration date of <code>access token</code></td></tr><tr><td>refresh_token</td><td>required</td><td>After the <code>access token</code> expires, you can use it to obtain other <code>access tokens</code>.</td><td>After the <code>access token</code> expires, you can use it to obtain other <code>access tokens</code>.</td></tr><tr><td>id_token</td><td>optional</td><td>ID token issued through <code>OpenIDConnect</code> extensions, including <code>Base64</code> encoded user credentials (including nonce)</td><td><code>ID token</code> issued through <a data-mention href="#openid-connect">#openid-connect</a>extensions, including <code>Base64</code> encoded user credentials (including <code>nonce</code>)</td></tr><tr><td>scope</td><td>required</td><td>Agree items to request consent from the user</td><td>Agree items to request consent from the user</td></tr><tr><td>token_type</td><td>required</td><td><code>Bearer</code></td><td>Type of token</td></tr></tbody></table>

\<Example>

```http
200 OK
Content-Type: application/json;charset=UTF-8
{
    "access_token": "eyJhbGciOiJSUzUxMiIsInR5cCI6ImF0K2p3dCIsImtpZCI6IjNCeDI2dFhlTVBxWUQ3UDNFZXRVQUo5TmY1YlZVdmpWZlQ2Q2ZraHY4ZlkifQ.eyJqdGkiOiJIY0VvRnlFalROZmpwVTlDNnlsUy0iLCJzdWIiOiI2NGRjN2UyODI5ZWNiNDAwNGRjODhhNWIiLCJpYXQiOjE2OTU3MTIxMTksImV4cCI6MTY5NTc5ODUxOSwic2NvcGUiOiJvcGVuaWQgdXNlciIsImNsaWVudF9pZCI6ImZvbyIsImlzcyI6Imh0dHBzOi8vYXV0aC1zZXJ2ZXIuZGV2LWRlbnRiaXJkLmNvbSIsImF1ZCI6ImZvbyJ9.wZLXm1LK4tcpMgu-vP7Qodvi_eCLEjzY09FreSsAysObgOQ_DInH6O3iH9ul3ByGFo5sYHuxok_9-yTUGDj1x5hOE23LHXQyF_vGwqOJjCDQ0PYoSzCnvZyVcYE4vt-8AscYc91RazkVWqqEWlXFHp-cwEXnvAjkZsX3maa8aM3QJDYfsoH4TKIgUh5ueG7DXoZzyWP20ZzlaS7BHV7Q1zGWA-YCZzKkPZdfrzmu7yC77Knj_W8LN5137BhX7hYhIQ653ajds6UnkjU_hGPkzO3KZ1Qx80BeVlD20MQX6lsAyw96ReBYYly0FmXHajubto_e3EarOx1l5tx6aL4AjSKH4VPu2zehVyC6fgFA5sfzTFZJjvQ4UTvlZEVuVlbU7thjjxU_Y9AebF8At7sQoU4odUzGbuTOLQthN3Eef4owNcb1AZnq_FCFIsj8br1_zcqmCNz9iyoa5cdPmeYIZURubjMQSqVAWj0hDOjQUcRTvfA3suPj_UgPQQUV1gu0",
    "expires_in": 86400,
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjNCeDI2dFhlTVBxWUQ3UDNFZXRVQUo5TmY1YlZVdmpWZlQ2Q2ZraHY4ZlkifQ.eyJzdWIiOiI2NGRjN2UyODI5ZWNiNDAwNGRjODhhNWIiLCJub25jZSI6IjVyZDl5d2xudjdoIiwiYXRfaGFzaCI6IlprTlN5dENnbk5pWGs2dkZ3R2RwQUEiLCJhdWQiOiJmb28iLCJleHAiOjE2OTU3MTU3MTksImlhdCI6MTY5NTcxMjExOSwiaXNzIjoiaHR0cHM6Ly9hdXRoLXNlcnZlci5kZXYtZGVudGJpcmQuY29tIn0.lf3yIYJfERuvWKQ9ojUGrUWz1pmoQCMOv4ajrYfxP-TWDjMg6Br2mmIJAytWbfeeXnApwy8TJ5G_xSEJKL6_w_mHVxL_FGr7LDNLSXsP8gB5-752m4wldCHvpNn32wqUc5e4OeNkmv5GqZkdW7hKPDPJgz_jCU5QIfIAPbN-FbOt3KiH26DtYImtsrAJSCXcpWiK3s8m9HCOk5nDoNFWADHtwORiKsBrt00BGgCNbdL38iSM6S8jB1ZQszW3HNpONNtC9IvZGtjlQPc_XFV3CKHOymTRRXdnI-SLYRevBJ-2nG5VfCEfCBwP53vXzeb2aVikhHMpKKWFsNdor1ZcodborWeWJoBR9DJt5WLEhZs3Ey3Zflaxybt8pY5-h4jg42mYGMkq1592zZ9H8KasNEtyXTtjopGW-aDM9Qt6T4Xd2zYbK_W-7FMYRAbUvPx8HxLKOFHXhfe5Vxeqn3ALFspeJ07TSauRZLtbwOhQhqMnENUVnV1xxbGWQkVLfQd7",
    "refresh_token": "WdcTGy80sF789exbXiVMhiufuPTqMMFHuvIVY0SBk-T",
    "scope": "openid user design-case file",
    "token_type": "Bearer"
}
```

## Scopes

A `Scope` is a string identifier used by the client to specify the range or permissions for accessing resources from a user's account. The `Scope` clearly informs the user about which data access permissions are being requested.

| Scope       | Description                                                       |
| ----------- | ----------------------------------------------------------------- |
| openid      | It provides[#oidc-openid-connect](#oidc-openid-connect "mention") |
| user        | You can read user profile information                             |
| design-case | You can read, create, and delete design-case information          |
| file        | You can read, download, upload, and delete files                  |

## Error Code Format

### **OAuth Authentication APIs Error Code**

<pre class="language-typescript"><code class="lang-typescript">interface AuthenticationErrorResponse {
  error: string;
<strong>  error_description: string;
</strong>}
</code></pre>

<table><thead><tr><th width="218.33333333333331">Field</th><th width="100">Type</th><th>Description</th></tr></thead><tbody><tr><td>error</td><td>string</td><td>OAuth 2.0 Error Field</td></tr><tr><td>error_description </td><td>string</td><td>OAuth 2.0 Error Field</td></tr></tbody></table>

### **Resource APIs Error Code**

```typescript
interface ErrorResponse {
  timestamp: ISODate;
  success: false;
  errorCode: string;
  message: string;
}
```

<table><thead><tr><th width="218.33333333333331">Field</th><th width="100">Type</th><th>Description</th></tr></thead><tbody><tr><td>timestamp</td><td>ISO Date</td><td>yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ</td></tr><tr><td>success</td><td>boolean</td><td>API Success or Faield boolean value</td></tr><tr><td>errorCode</td><td>string</td><td>API Error Code</td></tr><tr><td>message</td><td>string</td><td>API Error Message</td></tr></tbody></table>

## --- Resource APIs --- <a href="#resources" id="resources"></a>

## User <a href="#user" id="user"></a>

This requires user scope for the user API.

### Get User Info <a href="#get-user-profile-information" id="get-user-profile-information"></a>

Get user profile information

```http
GET /v1/users/me 
```

#### Request headers

<table><thead><tr><th width="168">Name</th><th width="109">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td>required</td><td><code>Bearer &#x3C;token></code></td></tr></tbody></table>

#### Response body structure

```json
{
  "email": "gildong@imagoworks.ai",
  "firstName": "Gildong",
  "lastName": "Hong",
  "profileImage": "https://dev-cloud-cdn.dentbird.com/public/profileImage/avalatte30@imagoworks.ai/ec5e20be-3675-4354-876c-78a48a8eda1c.png",
  "occupation": "Dentist"
}
```

## Design-Case

This requires design-case scope for the design case API.

### Get Case List

```http
GET /v1/design-cases 
```

#### Request headers

<table><thead><tr><th width="168">Name</th><th width="123">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td>required</td><td><code>Bearer &#x3C;token></code></td></tr></tbody></table>

#### Request query parameter

<table><thead><tr><th width="155">Parameter</th><th width="98.33333333333331">Type</th><th width="126">Constraints</th><th>Description</th></tr></thead><tbody><tr><td>lifecycle</td><td> string</td><td>optional</td><td><p>Filter design cases based on lifecycle status.</p><ul><li><code>CREATED</code>: Newly created design cases.</li><li><code>TRASHED</code>: Design cases moved to the trash.</li><li><code>DELETED</code>: Permanently deleted design cases.</li></ul></td></tr><tr><td>status</td><td>string</td><td>optional</td><td><p>Filter design cases based on status type.</p><ul><li><code>CREATED</code>: Design cases that are newly created.</li><li><code>DESIGNED</code>: Design cases that have been designed.</li><li><code>CAM</code>: Design cases that are in the CAM (Computer-Aided Manufacturing) stage.</li></ul></td></tr><tr><td>caseName</td><td> string</td><td>optional</td><td>Filter design cases by case name using a partial match (LIKE search).</td></tr><tr><td>referenceId</td><td>string</td><td>optional</td><td>Filter design cases by reference ID using an exact match.</td></tr><tr><td>page</td><td>number</td><td>required</td><td>Specifies the page number for pagination (1-based index, where the first page is 1).</td></tr></tbody></table>

#### Response body structure

```json
{
    "success": true,
    "data": {
        "items": [
            {
                "designCaseId": "20221103-000034",
                "createAt": "2022-11-03T07:51:39.420Z",
                "lifecycle": "TRASHED",
                "status": "DESIGNED",
                "caseName": "Sample Case 1 - Designed Crown",
                "updateAt": "2022-11-03T07:51:39.420Z",
                "isFlagged": false,
                "patientId": "",
                "importPlatform": "Dentbird",
                "projectType": "CROWN"
            },
            {
                "designCaseId": "20220908-000001",
                "createAt": "2022-09-08T01:25:20.990Z",
                "lifecycle": "TRASHED",
                "status": "DESIGNED",
                "caseName": "Sample Case 1 - Designed Crown",
                "updateAt": "2022-09-08T01:25:20.990Z",
                "isFlagged": false,
                "patientId": "",
                "importPlatform": "Dentbird",
                "projectType": "CROWN"
            }
        ],
        "totalCount": 2,
        "page": 1,
        "totalPage": 1,
        "count": 2,
        "hasNext": false,
        "hasPrev": false,
        "isFirst": true,
        "isLast": true
    }
}
```

### Get Case Details

*This API is provided only to contracted clients.*

```http
GET /v1/design-cases/{caseId}
```

Retrieves the details of a specific design case identified by `designCaseId`. The `designCaseId` can be obtained from the Get Case List API. The response includes comprehensive information about the design case, such as lifecycle status, case information, and associated mesh files. Note that the mesh blob files are compressed using [the Draco library](https://google.github.io/draco/), requiring a process to decode them into 3D files.

#### Reqeust headers

<table><thead><tr><th width="168">Name</th><th width="123">Type</th><th width="131">Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td>required</td><td><code>Bearer &#x3C;token></code></td></tr></tbody></table>

#### Request path parameter

<table><thead><tr><th width="168">Parameter</th><th width="123">Type</th><th width="130">Constraints</th><th>Description</th></tr></thead><tbody><tr><td>caseId</td><td>string</td><td>required</td><td>The unique identifier of the design case.</td></tr></tbody></table>

#### Response body structure

```json
{
    "success": true,
    "data": {
        "crownProjectType": "CROWN",
        "caseInfo": {
            "designCaseId": "20240605-260104",
            "createAt": "2024-06-05T08:25:08.390Z",
            "lifecycle": "CREATED",
            "status": "DESIGNED",
            "caseName": "untitled design case",
            "updateAt": "2024-06-05T08:30:42.896Z",
            "isFlagged": false,
            "patientId": "",
            "importPlatform": "Dentbird",
            "projectType": "CROWN"
        },
        "scanMeshList": [
            {
                "groupType": "0",
                "modelType": "upperBase",
                "meshFile": {
                    "downloadUrl": "<downloadUrl>",
                    "fileName": "ARCH/UPPER_BASE/default.drc.gz",
                    "fileId": "66602231f565f7196cb55afc"
                },
                "thumbnailFile": {
                    "downloadUrl": "<downloadUrl>",
                    "fileName": "thumbnail.png",
                    "fileId": "66602231f565f7196cb55b02"
                },
                "textureFiles": [
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "ARCH/UPPER_BASE/default.drc.gz",
                        "fileId": "66602231f565f7196cb55afc"
                    },
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "thumbnail.png",
                        "fileId": "66602231f565f7196cb55b02"
                    },
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "ARCH/LOWER_BASE/default.drc.gz",
                        "fileId": "66602231f565f7196cb55b0a"
                    },
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "thumbnail.png",
                        "fileId": "66602231f565f7196cb55b10"
                    }
                ]
            },
            {
                "groupType": "1",
                "modelType": "lowerBase",
                "meshFile": {
                    "downloadUrl": "<downloadUrl>",
                    "fileName": "ARCH/LOWER_BASE/default.drc.gz",
                    "fileId": "66602231f565f7196cb55b0a"
                },
                "thumbnailFile": {
                    "downloadUrl": "<downloadUrl>",
                    "fileName": "thumbnail.png",
                    "fileId": "66602231f565f7196cb55b10"
                },
                "textureFiles": [
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "ARCH/UPPER_BASE/default.drc.gz",
                        "fileId": "66602231f565f7196cb55afc"
                    },
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "thumbnail.png",
                        "fileId": "66602231f565f7196cb55b02"
                    },
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "ARCH/LOWER_BASE/default.drc.gz",
                        "fileId": "66602231f565f7196cb55b0a"
                    },
                    {
                        "downloadUrl": "<downloadUrl>",
                        "fileName": "thumbnail.png",
                        "fileId": "66602231f565f7196cb55b10"
                    }
                ]
            }
        ],
        "meshList": [
            {
                "modelType": "crown",
                "toothNumber": 36,
                "meshFile": {
                    "downloadUrl": "<downloadUrl>",
                    "fileName": "CROWN/CROWN/default.drc.gz",
                    "fileId": "66602231f565f7196cb55af2"
                },
                "thumbnailFile": {
                    "downloadUrl": "<downloadUrl>",
                    "fileName": "thumbnail.png",
                    "fileId": "66602231f565f7196cb55afe"
                }
            }
        ]
    }
}
```

### Download file

*This API is provided only to contracted clients.*

This API is provided only to contracted clients. Files are downloaded directly from the Dentbird server. When downloading a mesh-type file, you can specify the desired format as either PLY or STL. If no format is specified, the file will be downloaded in STL format by default.

#### Resource Information

```http
GET /v1/design-cases/{caseId}/download-file/{fileId}
```

The `{fileId}` is responded via the 'Get Case Details' API endpoint `GET /v1/design-cases/{caseId}`.

#### Reqeust headers

<table><thead><tr><th width="168">Name</th><th width="123">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td>required</td><td><code>Bearer &#x3C;token></code></td></tr></tbody></table>

#### Request path parameter

<table><thead><tr><th width="168">Parameter</th><th width="123">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>caseId</td><td>string</td><td>required</td><td>The unique identifier of case</td></tr><tr><td>fileId</td><td>string</td><td>required</td><td>The unique identifier of file</td></tr></tbody></table>

#### Request query parameter

<table><thead><tr><th width="168.10546875">Parameter</th><th width="122.6015625">Type</th><th width="130.6015625">Constraints</th><th>Description</th></tr></thead><tbody><tr><td>fileFormat</td><td>string</td><td>optional</td><td>Desired file format. Allowed values: <code>stl</code>, <code>ply</code>. Defaults to <code>stl</code> if omitted. Unsupported values will result in a <code>400 error</code>.</td></tr></tbody></table>

#### Response body

```
{file_content_as_raw}
```

### Transfer data to Dentbird Solution&#x20;

This API processes the client's uploaded data for use with Dentbird solutions.

Before calling this API, you must register the information of the files to be uploaded using the 'Register file information' API(`POST /v1/files/upload`), and subsequently upload the files via the Azure Storage pre-signed upload URL.

```http
POST /v1/design-cases/transfer
```

#### Request headers

<table><thead><tr><th width="168">Name</th><th width="123">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td>required</td><td><code>Bearer &#x3C;token></code></td></tr></tbody></table>

#### Request body form <a href="#file-manage" id="file-manage"></a>

<table><thead><tr><th>Parameter</th><th width="137">type</th><th width="127">Constraints</th><th>Description</th></tr></thead><tbody><tr><td>caseName</td><td>string</td><td>required</td><td>case name</td></tr><tr><td>projectType</td><td>string</td><td>required</td><td>Currently, only 'CROWN' is supported.</td></tr><tr><td>fileIds</td><td>string[]</td><td>required</td><td>The set of file Ids generated from the 'Register file information' API.</td></tr><tr><td>referenceId</td><td>string</td><td>required</td><td>It refers to the reference ID, which can be utilized subsequently for case tracking.</td></tr></tbody></table>

#### Request body example

```json
{
  "caseName": "untitled design case",
  "projectType": "CROWN",
  "fileIds": ["6512622222e0e4424b5dfe89", "BB46A43275248F9131DB0F9729AC6AD4"],
  "referenceId": "<your_reference_id>"
}
```

#### Response body sturcture

```json
{
  "success": true,
  "data": {
    "redirectUrl": "<redirect_url>"
  }
}
```

## File

### Register file information  <a href="#upload-file" id="upload-file"></a>

```http
POST /v1/files
```

#### Request headers

<table><thead><tr><th width="168">Name</th><th width="123">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td>required</td><td><code>Bearer &#x3C;token></code></td></tr></tbody></table>

#### Request body form <a href="#request-body-form.1" id="request-body-form.1"></a>

Request Body should be an array and each element of the array must follow the following object format:

<table><thead><tr><th width="215">Parameter</th><th width="124.33333333333331">type</th><th>Description</th></tr></thead><tbody><tr><td>fileName</td><td>string</td><td>file name</td></tr><tr><td>contentLength</td><td>number</td><td>file byte size</td></tr><tr><td>contentMD5</td><td>string</td><td>Provide the Content-MD5 value of your file, encoded in Base64 format.</td></tr><tr><td>category</td><td>string</td><td>It refers to the 'upload file' category. Currently, only 'CASE_INPUT' is supported.</td></tr></tbody></table>

#### Request body example  <a href="#response-body" id="response-body"></a>

```json
[
  {
    "fileName": "lower.ply",
    "contentLength": 12345,
    "contentMD5": "kS7IA7LOSeSlQQaNSVq1cA==",
    "category": "CASE_INPUT"
  },
  {
    "fileName": "upper.ply",
    "contentLength": 54321,
    "contentMD5": "u0akMnUkj5Ex2w+XKaxq1A==",
    "category": "CASE_INPUT"
  }
]
```

#### Response status <a href="#response-body" id="response-body"></a>

```
201 Created
```

#### Response body structure <a href="#response-body" id="response-body"></a>

```json
{
  "success": true,
  "data": [
    {
      "fileName": "mx.ply",
      "uploadUrl": "<pre_signed_file_upload_url>",
      "fileId": "6512622222e0e4424b5dfe89"
    },
    {
      "fileName": "mn.ply",
      "uploadUrl": "<pre_signed_file_upload_url>",
      "fileId": "6512622222e0e4424b5dfe8a"
    }
  ]
}
```

### Upload file

Uploading files to the cloud uses the Azure Storage pre-signed upload URL. Upload one file for each request.

#### Resource Information

```http
PUT {pre_signed_file_upload_url} 
```

The `{pre_signed_file_upload_url}` is generated via the 'Register file information' API endpoint `POST /v1/files`.

**Request URL example:**

```
{baseUrl}/users/640ef030b81817c032c85beb/cases/input/0de4c00b-a8fc-4692-9113-66e48aad813f.ply?sv=2022-11-02&spr=https&st=2024-03-15T02:11:23Z&se=2024-03-15T02:26:23Z&sr=b&sp=w&sig=652sgqHr05B41WMkzQ0wpxatQkWV1rV1Nirwf3RgbZA=
```

#### Request headers

<table><thead><tr><th width="168">Name</th><th width="123">Type</th><th>Constraints</th><th>Description</th></tr></thead><tbody><tr><td>Content-Type</td><td>string</td><td>required</td><td>application/octet-stream</td></tr><tr><td>x-ms-blob-type</td><td>string</td><td>required</td><td>BlockBlob</td></tr></tbody></table>

#### Request body form

```
{file_content_as_raw}
```

#### Response status

```
201 Created
```

***

## Appendix

### response\_mode

`response_mode` is a parameter in `OpenID Connect (OIDC)` and `OAuth 2.0` that specifies how the client will receive a response from the authentication server. This parameter allows the client to have more granular control over how it receives the response.

* **`query`**: The authentication server includes the response in the query string of the client's redirection URI. This is the default and is used in most of the authorization code flows.

```http
303 See Other
Location: https://client.example.com/callback
?code=LqhwVE1Upzt6sU0CEQ-zqWrFjm70wa5UCEN_A5QruQP
&state=n61p3c05rpk
&iss=https://auth-server.dev-dentbird.com
```

* **`fragment`**: The authentication server includes the response in the fragment (the part after #) of the client's redirection URI. This is mainly used in the implicit flow.

```http
303 See Other
Location: https://client.example.com/callback
#code=LqhwVE1Upzt6sU0CEQ-zqWrFjm70wa5UCEN_A5QruQP
&state=n61p3c05rpk
&iss=https://auth-server.dev-dentbird.com
```

* **`form_post`**: The authentication server sends the response to the client's Redirect URI using HTTP POST. This method is useful for transmitting the response without exposing sensitive information through the browser.

```http
200 OK
Content-Type: text/html

<html>
<body>
<form method="post" action="https://client.example.com/callback">
  <input type="hidden" name="code" value="AUTH_CODE"/>
  <input type="submit" value="Submit"/>
</form>
<script>document.forms[0].submit();</script>
</body>
</html>
```

* **`web_message`**: The authentication server sends the response using HTML5 Web Messaging (window\.postMessage()). This method can be used in frontend applications.

```http
200 OK
Content-Type: text/html

<html>
<body>
<script>
  window.opener.postMessage({ code: "AUTH_CODE" }, "https://client.example.com");
</script>
</body>
</html>

```

### **Reasons to Request Tokens from the Server**

When implementing OAuth 2.0 or OpenID Connect, it's important to understand where and how to request token issuance. While it's technically possible to request tokens directly from client-side applications like browser-based SPAs, there are important security considerations to keep in mind.

* **`Protecting the Client Secret`** : In the OAuth 2.0 authorization code flow, the Client Secret is used to authenticate the client application to the authentication server. If the token request is made directly from the client side, there's a risk of exposing the Client Secret. Server-side calls can securely store and use the client secret without exposing it to the end user or potential attackers.
* **`CSRF`** : Making the token request from the server side provides better mechanisms to prevent CSRF attacks. The server can implement CSRF prevention tokens and other measures more effectively than client-side applications.
* **`Token Storage`** : Access tokens, refresh tokens, and ID tokens should be stored securely. Storing tokens directly in client-side storage mechanisms (e.g., local storage) exposes them to theft through XSS attacks. On the server side, tokens can be securely stored in server-side sessions or other secure storage mechanisms.
* **`Preventing Token Leakage`** : If client-side applications interact directly with the authentication server, tokens can leak through browser history, logs, or referrer headers. Server-side implementations can prevent such leaks.
* **`Logging and Monitoring`** : Token requests and responses can be logged more effectively through server-side implementations. This can be crucial for auditing, monitoring, and detecting potential security threats.
* **`Network Security`** : In a server-side environment, advanced network security measures such as secure VPNs, firewalls, and encrypted traffic can be implemented. This might be more challenging to enforce in client-side applications.
* **`CORS`**
  * **`Browser Restrictions`** : Browsers restrict web pages from making requests to a domain other than the one that served the web page, a policy known as the "same-origin policy". If a client-side application tries to directly request a token from an authentication server of a different origin, it becomes a cross-origin request. If the authentication server doesn't set the appropriate CORS headers, the browser will block the request.
  * **`Exposure of Sensitive Operations`** : Even if the authentication server is configured to support CORS, making a direct token request from the client side exposes sensitive operations to the less secure browser environment. This increases the risk of man-in-the-middle attacks, token leakage, or other vulnerabilities.
  * **`Preflight Overhead`** : For certain types of requests, browsers perform a CORS preflight, an additional request to check if the cross-origin request is safe. This adds overhead and complexity to the process.

While client-side token requests might seem simpler and more direct, they come with significant potential security risks. For robust security, it's advisable to handle token issuance on the server side, ensuring that sensitive credentials, tokens, and other critical information are protected from exposure and potential attacks.

By handling token issuance on the server side and considering CORS, developers can ensure a more secure and reliable authentication and authorization process, protecting both end users and the resources they access.

<br>
