Connekt OAuth API
Let your users sign in with their Connekt account and access their social data โ securely, with their explicit consent. Built on standard OAuth 2.0 + PKCE. One integration handles students, commercial apps, and enterprise microservices.
Base URLs
https://connekt.social
https://connekt.social/api/v1
https://connekt.social/.well-known/openid-configuration
https://dev.connekt.social
Scopes
Request only the scopes your app actually needs. Users explicitly approve each scope on the consent screen.
| Scope | Permission | Data Returned |
|---|---|---|
profile.read |
๐ค View basic profile | username, avatar_url, bio, name, created_at |
profile.extended |
๐ View Connekt status | user_status, pioneer_status, is_pioneer, email_verified |
connections.read |
๐ View connections | followers_count, following_count, connection lists |
posts.read |
๐ฐ View posts | post content, media, likes, comments |
posts.write |
โ๏ธ Create posts | Create posts on behalf of user |
channels.read |
๐ก View channel memberships | subscribed channels, ownership status |
presence |
๐ข View online status | is_online, last_seen (approximate) |
notifications.write |
๐ Send notifications | Push Connekt in-app notifications |
PKCE โ RFC 7636
Use PKCE for all public clients (SPAs, mobile apps, Electron). The JS widget handles this automatically.
// Generate PKCE pair (browser or Node.js)
const verifier = crypto.randomUUID().replace(/-/g, '') + crypto.randomUUID().replace(/-/g, '');
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest('SHA-256', data);
const challenge = btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
// challenge โ code_challenge param
// verifier โ code_verifier in token exchange
Public Client Flow โ No client_secret
For apps that cannot keep a secret (SPAs, mobile, desktop). Register the app as a Public Client in Studio, then exchange the code with only the client_id and PKCE verifier.
POST https://connekt.social/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id=ck_your_client_id &code=AUTH_CODE_HERE &redirect_uri=https://yourapp.com/callback &code_verifier=YOUR_PKCE_VERIFIER
Note: No client_secret is sent. The PKCE verifier proves the caller is the same app that started the flow.
Client Credentials
Server-to-server access with no user involved. For agents, backend systems, and data pipelines. Your app must be registered with this grant type enabled.
POST https://connekt.social/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials &client_id=ck_your_client_id &client_secret=your_client_secret &scope=profile.read
Token Refresh
Access tokens expire after 24 hours. Use the refresh token to get a new pair. Refresh tokens rotate on each use (old one is invalidated). A RACP token.refreshed webhook is fired to your registered endpoint.
POST https://connekt.social/oauth/token/refresh Content-Type: application/x-www-form-urlencoded refresh_token=ckr_XyZwVu... &client_id=ck_your_client_id &client_secret=your_client_secret
Token Revocation โ RFC 7009
Revoke tokens when a user disconnects your app. Always returns 200 even if the token is not found (per RFC). Fires a RACP token.revoked webhook.
POST https://connekt.social/oauth/token/revoke Content-Type: application/x-www-form-urlencoded token=ckt_AbCdEf... &client_id=ck_your_client_id &client_secret=your_client_secret
Token Introspection โ RFC 7662 NEW
For resource servers and microservices that need to verify a token without calling /oauth/userinfo. Validates the token and returns its metadata. Only exposes data about tokens issued to your app.
POST https://connekt.social/oauth/token/introspect Content-Type: application/x-www-form-urlencoded token=ckt_AbCdEf... &client_id=ck_your_client_id &client_secret=your_client_secret
Active Token Response
{
"active": true,
"sub": "user-public-uuid",
"username": "kudakwashe",
"scope": "profile.read connections.read",
"client_id": "ck_your_client_id",
"token_type": "Bearer",
"exp": 1748000000,
"iat": 1747913600,
"grant_type": "authorization_code"
}
Invalid/Expired Token
{ "active": false }
API v1 Reference
All endpoints require Authorization: Bearer <access_token>. Rate limit headers are present on every response.
/api/v1/me
profile.read
Current authenticated user profile.
Example Response
{"status":"success","user":{"id":"uuid","username":"kudakwashe","name":"Kudakwashe M.","avatar_url":"https://...","bio":"...","is_online":true,"scopes_granted":["profile.read"]}}
/api/v1/me/connections
connections.read
User's followers or following. Params: type=followers|following, page, per_page (max 50).
Example Response
{"status":"success","type":"following","connections":[{"id":"uuid","username":"jane","avatar_url":"...","is_online":false}],"has_more":false,"page":1}
/api/v1/me/posts
posts.read
User's posts, newest first. Params: page, per_page (max 50).
Example Response
{"status":"success","posts":[{"id":"uuid","content":"...","media_url":"https://...","created_at":"2026-01-01T00:00:00","likes_count":42,"comments_count":7,"visibility":"public"}],"has_more":true,"total":88}
/api/v1/me/channels
channels.read
Channels the user is subscribed to.
Example Response
{"status":"success","channels":[{"id":"uuid","name":"Tech Talk ZW","subscriber_count":1200,"is_owner":false}],"total":3}
/api/v1/users/:id
profile.read
Look up any user by public_id or username.
Example Response
{"status":"success","user":{"id":"uuid","username":"tinodashe","name":"Tinodashe ...","avatar_url":"...","bio":"..."}}
/api/v1/posts
posts.write
Create a post on behalf of the user. Body: { content, visibility }.
Example Response
{"status":"success","post":{"id":"uuid","content":"Hello from my app!","visibility":"public","created_at":"2026-01-01T00:00:00"}}
Sign in with Connekt Widget
The fastest way to add Connekt authentication. Drop in a script tag, add a div. Works in any HTML page. PKCE is handled automatically.
1. Include the script
<script src="https://connekt.social/static/js/connekt-oauth.js"></script>
2. Add the button div
<div data-connekt-client-id="ck_your_client_id"
data-connekt-scopes="profile.read connections.read"
data-connekt-redirect-uri="https://yourapp.com/callback"
data-connekt-theme="dark">
</div>
3. Listen for the auth code
document.addEventListener('ckt:success', async (e) => {
const { code, state, verifier } = e.detail;
// Send to YOUR server โ never exchange the code client-side
const res = await fetch('/auth/connekt/callback', {
method: 'POST',
body: JSON.stringify({ code, state, verifier }), // Include PKCE verifier!
headers: { 'Content-Type': 'application/json' }
});
const { user } = await res.json();
console.log('Signed in as:', user.username);
});
document.addEventListener('ckt:error', (e) => {
console.error('Auth failed:', e.detail.error);
});
โ ๏ธ Security: Never expose client_secret client-side
For confidential apps, the client_secret must stay on your server. The widget gives you a code โ send that to your backend, which does the token exchange with the secret. Public apps (SPA/mobile) omit the secret entirely and use PKCE only.
Widget Attributes
| Attribute | Required | Description |
|---|---|---|
data-connekt-client-id |
Yes | Your app's client_id from Studio |
data-connekt-redirect-uri |
Yes | Must match a registered redirect URI |
data-connekt-scopes |
Yes | Space-separated scope list |
data-connekt-theme |
No | "dark" (default) or "light" |
data-connekt-mode |
No | "popup" (default) or "redirect" |
data-connekt-state |
No | Custom state value (auto-generated if omitted) |
Webhooks โ RACP Protocol
Receive real-time events when things happen to your users. OAuth webhooks use the same RACP protocol as Connekt Agents โ
same HMAC-SHA256 signing, same X-Connekt-Signature header, same User-Agent.
If you already verify RACP agent events, your verification code works here unchanged.
Available Events
token.issued
A user authorizes your app (new token granted)
token.revoked
A user revokes your app's access
token.refreshed
A token is refreshed (old token invalidated, new one issued)
user.post.created
A connected user creates a post (requires posts.read scope)
Webhook Payload Shape
{
"event": "token.issued",
"timestamp": 1748000000,
"platform": "connekt",
"api_version": "1.0",
"data": {
"user": { "id": "user-uuid", "username": "kudakwashe" },
"token_prefix": "ckt_AbCdEf",
"scopes": ["profile.read", "connections.read"],
"expires_in": 86400
}
}
Verify the Signature (Python)
import hmac, hashlib
def verify_connekt_webhook(payload_bytes, signature_header, webhook_secret):
"""Same code as RACP agent verification."""
expected = hmac.new(
webhook_secret.encode('utf-8'),
payload_bytes,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
# Flask example
@app.route('/webhook/connekt', methods=['POST'])
def connekt_webhook():
sig = request.headers.get('X-Connekt-Signature', '')
if not verify_connekt_webhook(request.data, sig, WEBHOOK_SECRET):
return 'Unauthorized', 401
event = request.json
if event['event'] == 'token.issued':
user = event['data']['user']
print(f"New user connected: {user['username']}")
return '', 200
Delivery Guarantees
- At-least-once delivery with 3 retries (1s โ 3s โ 9s backoff)
- 10-second request timeout per attempt
- Delivery is non-blocking โ never slows down the primary OAuth flow
- Your endpoint should return 200/201/202/204 to acknowledge
- All delivery attempts visible in Studio event log
Rate Limits
Enforced via Redis sliding window. The Retry-After header tells you exactly how long to wait.
| Plan | Calls / Day | Calls / Minute |
|---|---|---|
| Free | 500 | 30 |
| Developer | 5,000 | 120 |
| Pro | 50,000 | 600 |
Rate Limit Response Headers
X-RateLimit-Limit-Day: 5000 X-RateLimit-Remaining-Day: 4872 X-RateLimit-Limit-Minute: 120 X-RateLimit-Remaining-Minute: 117 X-RateLimit-Plan: developer X-Connekt-API-Version: 1.0
429 Too Many Requests
{
"error": "rate_limit_exceeded",
"error_description": "You have exceeded your API rate limit. Check the Retry-After header.",
"docs": "https://connekt.social/developers/docs/oauth#rate-limits"
}
Error Reference
All errors follow the OAuth 2.0 error format. Non-200 responses always have error and error_description fields.
| HTTP | error | Cause |
|---|---|---|
| 400 | invalid_request |
Missing or malformed parameter |
| 400 | invalid_grant |
Authorization code invalid, expired, or already used |
| 400 | unsupported_grant_type |
grant_type not supported by this app |
| 401 | invalid_client |
client_id/secret mismatch or app is inactive |
| 401 | invalid_token |
Bearer token missing, invalid, expired, or revoked |
| 403 | insufficient_scope |
Token does not have required scope |
| 404 | not_found |
Resource not found |
| 429 | rate_limit_exceeded |
Daily or per-minute limit reached |
OpenID Discovery
Standard OIDC discovery document โ lets OAuth libraries auto-configure from a single URL.
GET https://connekt.social/.well-known/openid-configuration
{
"issuer": "https://connekt.social",
"authorization_endpoint": "https://connekt.social/oauth/authorize",
"token_endpoint": "https://connekt.social/oauth/token",
"userinfo_endpoint": "https://connekt.social/oauth/userinfo",
"revocation_endpoint": "https://connekt.social/oauth/token/revoke",
"introspection_endpoint": "https://connekt.social/oauth/token/introspect",
"scopes_supported": ["profile.read", "profile.extended", "..."],
"grant_types_supported": ["authorization_code", "client_credentials", "refresh_token"],
"code_challenge_methods_supported": ["S256", "plain"]
}
Sample Apps & Integrations
The fastest way to get started is by following a reference implementation. Clone a repository and be up and running in minutes.
Python / Flask
Standard backend-only Authorization Code flow implementation.
Next.js Serverless
Modern React implementation using serverless routes and PKCE.
HTML / Node Widget
Quick drop-in integration using the Connekt JS Widget.