Tiquo
Integrations OverviewAirtableAsanaSlackGoogle AnalyticsMetabaseMixpanelPendoSegmentTableau (PAT)ActiveCampaignBrevoEmarsys Core API (WSSE)EventbriteFacebookGoogle AdsHighLevelInstagramKlaviyoMailchimpMailgunMicrosoft AdsSendGridTwitter (v2)HubSpotNotionAcuity SchedulingAirtable (Personal Access Token)BasecampCal.com (v2)CalendlyClickUpCodaConfluence Data CenterExpensifyGoogle CalendarGoogle SheetHarvestLinearMicrosoft Power BIMicrosoft TeamsMindbodyMondayOpenAIPerplexityPingboardPivotal TrackerProductboardQuickbaseServiceM8ServiceNowTeamworkTickTickTimelyTodoistTrafftTrelloWrikefal.aixAIZendeskIntercomAircall (OAuth)DixaFreshDeskFreshserviceFrontPlainRingCentralZoho DeskBrazeDialpadGoogleMicrosoftOutlookPodiumSednaSharePoint OnlineTwilioWhatsApp BusinessZoho MailBambooHRADPDeelEmployment HeroGustoHibob Service UserNamelyOracle Fusion Cloud (HCM)PaychexPayfitPaylocityPersonioRipplingSAP SuccessFactorsSage HRTSheetsUKG ProUKG ReadyWorkdayZoho PeopleQuickBooksBuildiumExact OnlineFreshBooksIntuitNetSuitePennylaneSageSage IntacctTwinfieldUnanetWave AccountingXeroZoho BooksSalesforceAffinityAttioCopperFreshsalesGainsight CCInsightlyKustomerMedalliaPipedriveTwenty CRMZoomInfoApaleoMewsMicrosoft Business CentralOdooSAP ConcurZuoraAcceloCoupa CompassZoho InvoiceAnrokAvalaraDocuSignDropbox SignPandadocSignNowLinkedInSplitwiseTikTok AdsJotformQualtricsRefinerTypeformShopifyCin7 CoreGoogle MapsRingoverListrakRydooTalentLMSApple Business ManagerCrunchbaseRocketReachOcean.ioFreepikEnergy Performance Certificates (Gov.UK)JustworksGristSAP S/4HANA Cloud3CX8x8Adobe CommerceBirdCloudbedsConstant ContactBufferCustomer.ioCrispFreeAgentGreenhouseMeta Marketing APIMollienocrm.ioOomnitzaDigitsPylonSage 200ShopwareAnvilShippoEasyPostAltrataMicrosoft PeopleMicrosoft IntuneCloudTalkGoogle FormsMaximizerMicrosoft PlannerSalesmsgSellercloudTallyTimifyUpsalesCleverReachHeymarketMailjetPleoProvenExpertTelegramToggl TrackASSA ABLOY Vingcard VisionlineASSA ABLOY Vingcard VostioASSA ABLOY TESA HotelASSA ABLOY SMARTairSalto KSSalto Space OnlineDormakabaOmnitecHotekTT LockWebLockISEOKleverKeyAperioISONASHIDSouthcoThird MillenniumSTidAxis CommunicationsBooking.comExpediaHotels.comAirbnbGoogle HotelsTripadvisorAgodaHotelbedsTravelgateXHyperguestRoibosReconlineTraviaOpenGDS.comMG BedbankDidatravelHotelREZHRSHotelnetworkGetaroomWinkBookeasyVRBOInntopiaHookusbookusHipcampSpot2niteCamping VisionMinistry of VillasTrip.comTravelokaTiketMakeMyTripHoteripKlookeDreamsSzallasEmerging Travel GroupCheck24Bed-and-Breakfast.itWorld2Meet (W2M)Ctoutvert / SecureholidayDespegarPriceTravelRoombeastMitchell CorpHRS AustraliaResonlineHostelworldHostelhopTablet MichelinMr & Mrs SmithHopperHotel TonightPitchupMoveriiLocalOTAAlaricBooknpayCultbookingGuestTractionLevartWeSpeakMake.comZapierPricelabsPricepointRategenieElastic HotelRoom Price GenieTurbosuiteUber EatsDeliverooDoorDashBolt Food
API and AuthenticationOAuth / OIDC

Customer Authentication

Use Tiquo as an OAuth 2.0 Authorization Server and OpenID Connect Provider

Customer Authentication with OAuth 2.0 / OIDC

Tiquo acts as a full OAuth 2.0 Authorization Server and OpenID Connect (OIDC) Provider. This lets you integrate customer authentication using the standard authorization code flow, which works with native mobile apps, server-side applications, and any platform that supports OAuth.

After a customer completes the OAuth flow, Tiquo issues JWT access tokens that work with the Customer API, just like tokens from the DOM Package.

Endpoints

EndpointURLDescription
Discoveryhttps://edge.tiquo.app/api/auth/.well-known/openid-configurationOIDC discovery metadata
OAuth Metadatahttps://edge.tiquo.app/api/auth/.well-known/oauth-authorization-serverOAuth 2.0 server metadata
Authorizationhttps://edge.tiquo.app/api/auth/oauth2/authorizeStart the authorization flow
Tokenhttps://edge.tiquo.app/api/auth/oauth2/tokenExchange code for tokens
UserInfohttps://edge.tiquo.app/api/auth/oauth2/userinfoGet user claims
JWKShttps://edge.tiquo.app/api/auth/jwksPublic keys for token verification

Setup

1. Register an OAuth Client

OAuth clients are registered through the Tiquo dashboard. Dynamic client registration is not available.

  1. Go to Settings > Identity Provider (IDP).
  2. In OAuth Clients, click Create OAuth Client.
  3. Enter a name and the exact redirect URI or URIs used by your application.
  4. Copy the client_id and client_secret. Store the secret securely; confidential clients need it during token exchange.

2. Authorization Flow

Redirect the customer to the authorization endpoint:

https://edge.tiquo.app/api/auth/oauth2/authorize?
  client_id=your_client_id
  &response_type=code
  &redirect_uri=https://yourapp.com/callback
  &scope=openid profile email offline_access
  &state=random_state_value
  &code_challenge=your_code_challenge
  &code_challenge_method=S256
ParameterRequiredDescription
client_idYesYour OAuth client ID
response_typeYesMust be code
redirect_uriYesWhere to redirect after authentication
scopeNoSpace-separated scopes. Include offline_access when the application needs a refresh token.
stateRecommendedRandom value for CSRF protection
code_challengeRecommendedPKCE code challenge (S256 method)
code_challenge_methodRecommendedMust be S256 when using PKCE

The customer will see a sign-in page where they authenticate with their email (via OTP). After authentication, Tiquo redirects back to your redirect_uri with an authorization code:

https://yourapp.com/callback?code=auth_code_here&state=random_state_value

3. Exchange Code for Tokens

Exchange the authorization code for tokens:

curl -X POST "https://edge.tiquo.app/api/auth/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=auth_code_here" \
  -d "redirect_uri=https://yourapp.com/callback" \
  -d "client_id=your_client_id" \
  -d "client_secret=your_client_secret" \
  -d "code_verifier=your_code_verifier"

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "rt_xxx...",
  "id_token": "eyJhbGciOiJSUzI1NiJ9...",
  "scope": "openid profile email offline_access"
}

4. Use the Access Token

The access token works with the authenticated Customer API endpoints:

curl -X GET "https://edge.tiquo.app/api/client/v1/profile" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..."

Supported Grant Types

Grant TypeDescription
authorization_codeStandard authorization code flow (with optional PKCE)
refresh_tokenExchange a refresh token for new tokens

Scopes

ScopeDescription
openidRequired for OIDC. Returns an ID token.
profileIncludes name and profile information in the ID token
emailIncludes email address in the ID token
offline_accessRequests a refresh token so the application can renew access after the access token expires

PKCE Support

Tiquo supports Proof Key for Code Exchange (PKCE) using the S256 challenge method. PKCE is recommended for all clients and is required for public clients (like mobile apps and single-page applications) that cannot securely store a client secret.

To use PKCE:

  1. Generate a random code_verifier (43-128 characters, URL-safe)
  2. Compute the code_challenge as the Base64-URL-encoded SHA-256 hash of the verifier
  3. Include code_challenge and code_challenge_method=S256 in the authorization request
  4. Include the original code_verifier in the token exchange request

Token Refresh

Refresh tokens are issued only when the original authorization request includes the offline_access scope. If your application does not request that scope, omit refresh-token handling.

To get a new access token using a refresh token:

curl -X POST "https://edge.tiquo.app/api/auth/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=rt_xxx..." \
  -d "client_id=your_client_id" \
  -d "client_secret=your_client_secret"

Refresh tokens are rotated on each use. Always store and use the new refresh token from the response.

UserInfo Endpoint

Retrieve the authenticated user's claims:

curl -X GET "https://edge.tiquo.app/api/auth/oauth2/userinfo" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..."

Response:

{
  "sub": "user_abc123",
  "email": "customer@example.com",
  "name": "John Doe"
}

JWKS (Token Verification)

To verify JWT tokens yourself, fetch the public keys from the JWKS endpoint:

curl "https://edge.tiquo.app/api/auth/jwks"

The response contains the RSA public key(s) in JWK format. Tokens are signed with RS256.

Token Details

TokenAlgorithmLifetimeIssuerAudience
Access tokenRS2561 hourhttps://auth.tiquo.apptiquo-client-api
ID tokenRS25610 hourshttps://auth.tiquo.appYour client ID
Refresh tokenN/A30 daysN/AN/A

Access Token Claims

{
  "sub": "user_abc123",
  "email": "customer@example.com",
  "token_source": "oauth",
  "organization_id": "org_xyz",
  "org_customer_id": "cust_456",
  "customer_number": "CUST-000001",
  "client_id": "your_client_id",
  "scope": "openid profile email offline_access",
  "iss": "https://auth.tiquo.app",
  "aud": "tiquo-client-api",
  "exp": 1706580000,
  "iat": 1706576400
}

Note that OAuth tokens include the client_id and scope claims, which are not present in DOM Package tokens.

ID Token Claims

The ID token is returned when the openid scope is requested. Treat the claims returned by the provider as the authoritative claim set for the signed-in customer; do not assume that requesting an additional scope will expose a particular field unless that field is present in the returned token or UserInfo response.

Native Mobile App Integration

iOS (Swift)

Use ASWebAuthenticationSession to handle the OAuth flow in iOS:

import AuthenticationServices

let authURL = URL(string: "https://edge.tiquo.app/api/auth/oauth2/authorize?client_id=\(clientId)&response_type=code&redirect_uri=myapp://callback&scope=openid%20profile%20email%20offline_access&code_challenge=\(codeChallenge)&code_challenge_method=S256")!

let session = ASWebAuthenticationSession(
    url: authURL,
    callbackURLScheme: "myapp"
) { callbackURL, error in
    guard let url = callbackURL,
          let code = URLComponents(url: url, resolvingAgainstBaseURL: false)?
              .queryItems?.first(where: { $0.name == "code" })?.value
    else { return }

    // Exchange the code for tokens
    exchangeCodeForTokens(code: code, codeVerifier: codeVerifier)
}

session.presentationContextProvider = self
session.start()

Android (Kotlin)

Use Custom Tabs or AppAuth for the OAuth flow:

val authUri = Uri.parse("https://edge.tiquo.app/api/auth/oauth2/authorize")
    .buildUpon()
    .appendQueryParameter("client_id", clientId)
    .appendQueryParameter("response_type", "code")
    .appendQueryParameter("redirect_uri", "myapp://callback")
    .appendQueryParameter("scope", "openid profile email offline_access")
    .appendQueryParameter("code_challenge", codeChallenge)
    .appendQueryParameter("code_challenge_method", "S256")
    .build()

val customTabsIntent = CustomTabsIntent.Builder().build()
customTabsIntent.launchUrl(context, authUri)

How It Works with the Customer API

The OAuth flow issues the same type of JWT access tokens as the DOM Package. Once you have an access token, you use it with the Customer API in exactly the same way:

  1. Register an OAuth client under Settings > Identity Provider (IDP) > OAuth Clients and configure its redirect URIs
  2. Redirect the customer to the authorization endpoint
  3. The customer signs in (via email OTP on the Tiquo sign-in page)
  4. Tiquo redirects back to your app with an authorization code
  5. Your app exchanges the code for an access token, ID token, and—when offline_access was requested—a refresh token
  6. Use the access token with Customer API endpoints (/profile, /orders, /bookings, /enquiries)
  7. When the access token expires, use the refresh token to get a new pair

The key difference from the DOM Package is that OAuth uses a redirect-based flow, while the DOM Package handles everything in-page. Choose based on your platform and requirements.

On this page