Authentication
General
The Digitail API uses the OAuth 2.0 Standard for authentication paired up with the Authorization Code Grant with PKCE support.
OAuth 2.0 Authorization Code Grant with PKCE offers robust security features suitable for protecting sensitive clinic information:
- Enhanced Security: PKCE mitigates code interception and replay attacks by adding a verification step during the authentication process.
- User Consent: OAuth 2.0 standards ensure that users explicitly grant permission for applications to access their data, maintaining privacy and compliance with regulations.
- Simplified Integration: OAuth 2.0 is widely supported across programming languages and platforms, enabling developers to integrate with ease.
Set-Up
Integrating with the Digitail API involves the following steps:
- Register Your Application: Obtain API credentials by completing the access form
- Implement OAuth 2.0 Flow: Follow the OAuth 2.0 Authorization Code Grant with PKCE flow to authenticate your application and obtain access tokens.
- Access Data: Utilize the access token to make authorized requests to Digitail API endpoints and retrieve clinic data.
You can add the retrieved access token directly in the documentation page to try out the endpoints easier
Implementing OAuth 2.0 Flow
Generate code_verifier, code_challenge and state variables. These variables are used to ensure the integrity and security of generating & retrieving the access_token that follows. code_verifier should be a cryptographically random generated string with lowercase & uppercase letters, digits and the punctuation characters -._~ between 43 and 128 characters long. code_challenge is the base64 url encoded version of the sha256 hashing of the code_verifier. state is a randomly generated uri encoded string used by your app to protect youself against CSRF attacks that is used to verify the integrity of the response.
Store the code_verifier and state variables locally.
More information here.
From your software, add a button "Connect with Digitail" that will redirect the user to the following url:
curl -L https://vet.digitail.io/oauth/authorize
?response_type=code
&client_id={client_id}
&client_secret={client_secret}
&redirect_uri=https://your-redirect-url.com/callback
&state={state}
&code_challenge={code_challenge}
&code_challenge_method=S256Digitail will prompt the user for authentication
The user authenticated and gives consent to give access to data specified.
Digitail will redirect back to the callback URL with the auth code & state params in the URL
The code is available for only 10 minutes and should be used immediately to request an access_token
Request an access_token by sending the following POST request:
curl -X POST
-d grant_type=authorization_code
-d client_id={client_id}
-d client_secret={client_secret}
-d redirect_uri=https://your-redirect-url.com/callback
-d code_verifier={code_verifier}
-d code={code}
https://vet.digitail.io/oauth/tokenDigitail will respond with the payload:
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...",
"refresh_token": "def50200a1b2c3..."
} Using the access token
Send the access token on every API request in the Authorization header:
GET https://vet.digitail.io/api/v1/appointments
Authorization: Bearer {access_token}
Accept: application/json Requests run in the context of the clinic that belongs to the user who authorized your application. If that user belongs to more than one clinic, select one by sending its id in the X-ClinicId header. Without the header, the user's default clinic is used.
Token lifetimes
Token | Valid for | Notes |
|---|---|---|
Authorization code | 10 minutes | Exchange it for tokens immediately. |
Access token | 1 year | expires_in in the token response, in seconds. |
Refresh token | 1 year | Counted from the moment it is issued. |
Store both tokens securely and treat them like passwords. Only the access token is ever sent to the API. The refresh token is only ever sent to the token endpoint.
Refreshing the access token
Nothing refreshes automatically. When the access token expires, or ahead of time if you prefer, request a new one from the token endpoint using therefresh_token grant. PKCE parameters are not needed for this call.
curl -X POST https://vet.digitail.io/oauth/token \
-d grant_type=refresh_token \
-d refresh_token={refresh_token} \
-d client_id={client_id} \
-d client_secret={client_secret} {
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz...",
"refresh_token": "def50200a1b2c3..."
} Every refresh returns a new access token and a new refresh token, and revokes both of the old ones in the same call. Refresh tokens are single use:
- Replace the stored refresh token with the new one as soon as the response arrives.
- Do not run two refreshes in parallel for the same user. The second one fails because the first already revoked the token it is presenting.
- Refreshing at least once a year keeps the session alive indefinitely, because each refresh token is valid for one year from issuance.
The token endpoint is rate limited separately from the API, at 60 requests per minute per IP address.
Handling expired or revoked tokens

What you see | Cause | What to do |
|---|---|---|
401 Unauthorized from an API endpoint | Access token expired or revoked | Refresh, then retry the request. |
401 from /oauth/token with "error": "invalid_request" and a hint of Token has expired or Token has been revoked | Refresh token is dead | Send the user through the authorization flow again. |
401 from /oauth/token with "error": "invalid_client" | Wrong client_id or client_secret | Check your credentials. |
400 from /oauth/token with "error": "invalid_grant" | Authorization code expired, reused, or wrong code_verifier / redirect_uri | Restart the authorization flow. |
OAuth 2.0 Flow Diagram
