DocumentationCustomer profiles

Customer profiles

v1

Group customer accounts and embed secure onboarding without exposing your API keys.

One profile per customer or brand

Profiles group accounts, posts, media and analytics within your workspace and mode. Set external_id to your own customer ID. Your API key stays on your server; customers connect through a short-lived hosted link.

TypeScript
const { data: profile } = await castrook.profiles.create({
  name: 'Acme Studio',
  external_id: 'customer_42',
});

const { data: session } = await castrook.connectSessions.create({
  profile_id: profile.id,
  platforms: ['instagram', 'facebook', 'tiktok', 'youtube', 'pinterest', 'linkedin'],
  return_url: 'https://your-app.com/connections',
  embed_origin: 'https://your-app.com',
});

// Send only session.url to your customer's browser.
// The link expires in 30 minutes by default.

Use profiles:read to list/get profiles and profiles:write to create/update/delete them. Connection sessions use accounts:write to create/revoke and accounts:read to inspect. Existing account assignment uses PATCH /accounts/{id} with { profile_id: profile.id }, or { profile_id: null } to unassign.

Hosted onboarding

Open the returned url in a new page. The customer authorizes the selected platforms without creating a Castrook account. The link is a secret capability: share it only with this customer, keep it out of analytics and logs, and create a new session for another customer. Set expires_in from 60 to 1,800 seconds to shorten its lifetime.

The customer can finish after connecting at least one account. Connecting all selected platforms completes the session automatically. A revoked, expired or completed session cannot start another connection.

LinkedIn defaults to personal publishing. The customer can choose advanced profile and Page access when the required permissions are enabled. To start that flow directly, add start=linkedin and connection_type=community to the returned hosted URL. The customer still reviews and authorizes access; inspect each returned account’s capabilities. LinkedIn authorization flows

Embedded onboarding

Set embed_origin to your exact HTTPS origin, without a path or trailing slash. Only this origin can frame the portal. Platform authorization opens in a top-level popup; allow popups and preserve the customer’s explicit click.

HTML
<iframe
  id="castrook-connect"
  src="SESSION_URL_FROM_YOUR_SERVER"
  title="Connect social accounts"
  style="width:100%;height:560px;border:0"
  referrerpolicy="no-referrer"
></iframe>
JavaScript
const frame = document.querySelector('#castrook-connect');

window.addEventListener('message', async (event) => {
  if (event.origin !== 'https://castrook.com') return;
  if (event.source !== frame.contentWindow) return;
  if (event.data?.type !== 'castrook.connection') return;
  if (event.data?.session_id !== expectedSessionId) return;
  if (event.data?.status !== 'completed') return;

  // Your backend verifies the stored session ID under the signed-in customer.
  // Never trust browser messages alone to grant customer permissions.
  await fetch('/your-api/verify-connection', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ session_id: expectedSessionId }),
  });
});

Verify completion on your server

YouTube connections ask the channel owner to accept the current privacy policy and terms in the hosted popup before authorization starts. That choice explicitly includes collecting and displaying YouTube video statistics; OAuth alone is not analytics consent.

TypeScript
const { data: session } = await castrook.connectSessions.get(sessionId);

if (session.status === 'completed') {
  const { data: accounts } = await castrook.accounts.list({
    profile_id: session.profile_id,
  });
  // Save account IDs under the customer's authenticated record.
}

Return URLs do not carry credentials. The completion message contains only session_id, profile_id, status and account_ids. Revoke a link with connectSessions.revoke(id). Before deleting a profile, move or unassign its accounts, finish or cancel pending posts, and delete its media. Completed post history remains available.

Keep customer data together

Include profile_id in uploads and posts. Every selected account and profile-owned asset must belong to that profile. Resource APIs reject cross-workspace, cross-mode and incompatible profile relationships. List accounts/posts/media or analytics with the same profile_id filter.

Destination-specific content · Upload media · Performance analytics