Connect with Corteksa — Partner Integration Guide
Integrations — Connect with Corteksa — Partner Integration Guide
Audience: an external app's backend developer (e.g. wieeo) letting a Corteksa customer connect their workspace and sync data.
TL;DR — the simple way (recommended): the customer generates an API key in
Corteksa and pastes it into your app. Your backend validates it with one call
(GET /api/v1/me), stores it, and uses it against the REST API. No OAuth, no
redirect, no app registration. One key = one workspace. This is the ClickUp
"personal token" model, and it's the fastest path to a working integration.
Prefer a one-click "Connect" button and don't want customers copy-pasting keys? That's the OAuth flow — see Advanced: OAuth Connect button at the end. Start with the API key below unless you specifically need it.
1. The flow
sequenceDiagram
participant U as Customer
participant W as wieeo backend
participant C as Corteksa API
U->>W: paste API key, click Connect
W->>C: validate key via the me endpoint
C->>W: 200 with workspace name and scopes
W->>W: store host and key, show Connected to Acme2. Which Corteksa host to use
The host decides which Corteksa database the request hits — before the key is even read. So it matters, and it differs by customer type:
| Customer type | Host | What to do |
|---|---|---|
| Standard (shared/free tier — the majority) | app.corteksa.info — fixed | Hardcode it. The key alone resolves the workspace; don't ask for a URL. |
| Enterprise (their own Corteksa domain) | e.g. acme.corteksa.info | Ask once (a "custom domain" field). The key only works on its own host. |
Store the host with the key after connecting, and reuse it for every call.
Throughout this doc, {HOST} = the host chosen here.
3. Connect — validate the pasted key with GET /api/v1/me
When the customer pastes a key and clicks Connect, call /me to (a) confirm the
key is valid and (b) get the workspace name to display. Send the key as a Bearer
token or the X-Api-Key header — both work:
200 — valid key:
→ Store { host, key }, and show "Connected to Acme Sales." You can also
pre-check scopes to warn if a permission you need is missing.
401 — invalid / revoked / expired key → reject with "That key isn't valid."
/me needs no scope — any valid key can call it. workspace_id is null for
enterprise/dedicated tenants (tenant_type: "dedicated"); the key still works.
4. Calling the API with the key
Send the key on every request against the customer's host:
Writing records — important: the data body is keyed by each field's slug
(e.g. name-8fk2), not its display name — a display-name key can 400 on a required field.
A key can only reach the objects/actions in its scopes; anything else returns 403.
See every key-reachable endpoint in the Integration API Reference.
5. Scopes
Scopes are route-name strings: {action}.{objectSlug} — e.g. read.contacts,
create.contacts, update.contacts, delete.contacts. The customer picks them
when they mint the key. You can see a key's granted scopes in the /me response,
so check upfront that the ones you need are present. Confirm the exact object slugs
per customer — Corteksa schemas are customizable.
6. Disconnecting
The customer revokes the key in Corteksa (Settings → API Keys → Revoke). Your very
next call returns 401. Treat a sudden 401 as "disconnected": delete the
stored key and prompt the customer to reconnect with a fresh one.
7. Security checklist
- The key is a secret — store it encrypted, server-side, per customer. Never in a browser, app bundle, or logs.
- Store the host alongside the key — enterprise customers aren't on
app.corteksa.info. - Handle
401as disconnected → clear the stored key and re-prompt. - Never log the key; log only the
token_prefixif you need a reference.
Advanced: OAuth "Connect" button
Only reach for this if you're publishing a listed integration and want a one-click "Connect with Corteksa" button instead of customers pasting keys. It's more moving parts (a global app registration, a redirect, a consent screen) for a smoother UX. The API key flow above needs none of it.
Setup (one-time, done on the Corteksa side)
A Corteksa super-admin registers your app once (global registry) and hands you:
| Env var | What it is |
|---|---|
CORTEKSA_CLIENT_ID | Your app's public id (crtk_app_…) — same for every customer |
CORTEKSA_CLIENT_SECRET | Your app secret — server-side only |
CORTEKSA_REDIRECT_URI | Your callback, e.g. https://api.wieeo.com/api/v1/integrations/corteksa/oauth/callback — exact match |
You are a confidential client (you have a backend), so you authenticate the
token exchange with client_secret. One registration serves every customer,
hyper and enterprise alike — only the host differs (same rule as §2).
The flow
sequenceDiagram
participant U as User browser
participant W as Your backend
participant C as Corteksa
U->>W: clicks Connect Corteksa
W->>U: redirect to Corteksa consent page
U->>C: logs in, clicks Approve
C->>U: redirect to your callback with code and state
U->>W: GET your callback code state
W->>C: POST oauth token with code and client_secret
C->>W: access_token refresh_token expires_in
W->>W: store token refresh_token host per customer-
Redirect the browser to the consent page (generate a random
statefirst):textThis is the Corteksa web app (it renders approve/deny), not the API.
-
User approves → browser returns to your
redirect_uriwith?code=…&state=…. Verifystate. Thecodeis single-use and expires in 60 seconds. -
Exchange the code for tokens (server-to-server):
httpResponse (raw RFC 6749 JSON):
{ access_token: "crtk_oauth_…", refresh_token, token_type, expires_in, scope }. -
Store
{ host, access_token, refresh_token, expires_at }per customer. The token carries the workspace — you don't trackworkspace_id. (You can callGET /api/v1/mewith thecrtk_oauth_token too, to show the workspace name.)
Refresh
Access tokens last ~1 hour. Refresh with grant_type: "refresh_token" (+ client_id
/ client_secret). Refresh tokens rotate — every refresh returns a new
refresh_token and invalidates the old one; always persist the new value.
Disconnect / revoke
- You revoke:
POST https://{HOST}/api/v1/oauth/revoke{ token, client_id, client_secret }(RFC 7009). - The customer revokes in Corteksa (Settings → Connected apps) → your tokens stop
immediately → treat a
401as disconnected.
Security
client_secret server-side only · state on every authorize · exact redirect_uri
· tokens are secrets, stored per customer · rotate the refresh_token on every refresh.