Corteksa
GuidesIntegrations

Connect with Corteksa (Partners)

Connect with Corteksa (Partners)

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

1. Customer (in Corteksa)  Settings → API Keys → New key → copy it
2. Customer (in wieeo)     paste the key → click Connect
3. wieeo backend           GET https://{HOST}/api/v1/me   (with the key)
                             200 → store {host, key}; show "Connected to <Workspace>"
                             401 → "That key isn't valid"
4. wieeo syncs             GET/POST https://{HOST}/api/v1/object/data/:slug  (with the key)

2. 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 typeHostWhat to do
Standard (shared/free tier — the majority)app.corteksa.netfixedHardcode it. The key alone resolves the workspace; don't ask for a URL.
Enterprise (their own Corteksa domain)e.g. acme.corteksa.netAsk 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:

GET https://{HOST}/api/v1/me
Authorization: Bearer crtk_live_…

200 — valid key:

{
  "message": "Success",
  "data": {
    "workspace_name": "Acme Sales",
    "workspace_id": 42,
    "tenant_type": "hyper",
    "scopes": ["read.contacts", "create.contacts", "update.contacts"]
  }
}

→ 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:

GET https://{HOST}/api/v1/object/data/contacts
Authorization: Bearer crtk_live_…

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.

POST https://{HOST}/api/v1/object/data/contacts
Authorization: Bearer crtk_live_…
Content-Type: application/json

{ "data": { "name-8fk2": "Sara", "phone-p0zx": "+20…" } }

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.net.
  • Handle 401 as disconnected → clear the stored key and re-prompt.
  • Never log the key; log only the token_prefix if 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 varWhat it is
CORTEKSA_CLIENT_IDYour app's public id (crtk_app_…) — same for every customer
CORTEKSA_CLIENT_SECRETYour app secret — server-side only
CORTEKSA_REDIRECT_URIYour 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

  1. Redirect the browser to the consent page (generate a random state first):

    https://{HOST}/en/oauth/authorize
      ?client_id=<CORTEKSA_CLIENT_ID>
      &redirect_uri=<CORTEKSA_REDIRECT_URI>   (URL-encoded, exact match)
      &scope=read.contacts%20create.contacts%20update.contacts
      &state=<random-opaque-string>
      &response_type=code

    This is the Corteksa web app (it renders approve/deny), not the API.

  2. User approves → browser returns to your redirect_uri with ?code=…&state=…. Verify state. The code is single-use and expires in 60 seconds.

  3. Exchange the code for tokens (server-to-server):

    POST https://{HOST}/api/v1/oauth/token
    Content-Type: application/json
    
    {
      "grant_type": "authorization_code",
      "code": "<code>",
      "redirect_uri": "<CORTEKSA_REDIRECT_URI>",
      "client_id": "<CORTEKSA_CLIENT_ID>",
      "client_secret": "<CORTEKSA_CLIENT_SECRET>"
    }

    Response (raw RFC 6749 JSON): { access_token: "crtk_oauth_…", refresh_token, token_type, expires_in, scope }.

  4. Store { host, access_token, refresh_token, expires_at } per customer. The token carries the workspace — you don't track workspace_id. (You can call GET /api/v1/me with the crtk_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 401 as 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.

On this page