Lovelio Connect - partner apps and connected apps
Signed in? Ask Lovelio this question inside the app - it answers from this same page.
Lovelio Connect is the developer platform for software companies that want to integrate with Lovelio - job boards, background checkers, assessment tools, accounting systems and anything else an agency runs alongside its ATS. It is fully self-serve: a developer signs up, gets a sandbox, builds and tests against the real API, and submits the integration for review without talking to anyone.
Connect is only for apps OTHER agencies connect to from the public directory. Somebody building one integration for one agency - their own, or a client's - needs none of it: the agency gives them an API key from Settings > API keys and they call the V1 API directly. The developers page, the docs and the empty portal all say so, because a review flow for an app nobody else connects to is wasted work. There is no separate "private app" class in the portal, deliberately (Brett, 2026-08-11).
Signing up
- The portal lives at lovelio.ai/developers/portal. Sign-in is a work email plus a six-digit code - no password.
- Connect is in private testing right now, so the public For Developers page does not link to the portal. The portal itself works for anyone who has the URL. The page asks visitors to request a demo instead, and the link goes back the day Connect opens.
- The first verified developer founds the workspace as its owner. Later developers verify their work email, then wait for owner approval. The owner sees Workspace members on the portal home page and approves, removes or restores access there. Removed members cannot sign back in until the owner restores them.
- Brett and Darren receive an email when each new developer verifies their account, including members awaiting owner approval. Returning sign-ins do not send signup alerts. Review submission still sends its own notification.
- Free email addresses (gmail and similar) are not accepted. The work email domain is how Lovelio knows who the company is.
Five steps on one page
- Creating an integration is one form, "Tell Lovelio about your app": name, website, one sentence on what the product does, does it write anything back, does it touch money. Lovelio does everything else from that form: derives the access, drafts the listing, mints the client ID and secret (shown once with the .env block), registers a placeholder callback and connect address, and creates the sandbox. There is no Create OAuth client button and no Create sandbox button; a fresh integration has all of them.
- An integration's page in the portal is five steps, all open on one page (since 2026-09-05, after the first partner could not find their way through the old log): 1 Sign in, 2 Get a sandbox, 3 Write your listing, 4 Request approval, 5 Go live. Each step carries a one-word status (Ready, Setting up, Needs a name, In review, Live) and the step that needs the developer is outlined in pink. Steps are information, never locks: nothing in step 2 has to be finished before step 3 or 4.
- Step 2 holds the whole build: Open sandbox, Copy setup prompt (with "I am not using an agent" linking to /docs/connect-flow), a warning when a localhost callback is registered, any refused connect attempt naming the scopes, and "Seen in your sandbox so far": a count of how many things Lovelio has watched the developer's code do, labelled "Each line ticks itself the first time your code does it". Until a line is seen it says what to do: the first is "Open your sandbox, go to Settings > Connected apps and connect this app". The sandbox agency lists the developer's own app there, marked "In testing", at any status, so the partner runs the flow exactly as an agency will (BUG-182). Lovelio's own checks and Run checks again sit under it.
- Under the steps sit four panels behind tabs: Keys and callback, Access, Sandbox, Usage. The listing is edited in step 3 itself. A dated History of what You and Lovelio did is folded under the page.
- An integration that never went live can be deleted from the bottom of its own page: a draft, one in review, one Lovelio did not approve. Two clicks, and the sandbox, the keys and the listing go with it. Once an app is approved and in the directory, or Lovelio has stopped it, the control is not there and removal goes through hello@lovelio.ai (BUG-172).
- There is no progress bar, no checklist, no certification button and no confirmation ticks.
The portal distinguishes a signed-out session from a temporary connection failure and offers Retry connection. Each integration has a bookmarkable URL. Email sign-in offers Resend code, code autofill and expiry feedback.
Calls, progress and credentials
The Sandbox panel shows the current environment base URL and the sandbox key's masked identifier. A 401 means checking the full key and environment. REST errors link to the public error guide; unknown REST paths return JSON 404 and unsupported methods return JSON 405 with Allow. OAuth and MCP retain their own protocol responses.
Opening webhook activity never counts as a partner API call. The steps and webhook activity refresh every 10 seconds in a visible tab and on return. Temporary failures keep the last result and show retry guidance. Submit's blockers are listed in the box at the bottom of the log from the start, so nothing is a surprise. Invalid or duplicate redirect input stays in the field with a correction message.
The webhook catalogue is GET /api/v1/webhooks/events with webhooks:read; the Sandbox panel links to it and the signing guide. Docs and OAuth discovery are public. The catalogue and agency records require authentication.
Browser apps call the partner's backend. Keep API keys, client secrets and tokens in private server storage. REST scripts use a key; MCP reads and writes use signed-in OAuth consent. Lovelio hashes API keys and client secrets for validation and also encrypts sandbox keys for certification and recovery. The public directory describes apps; agencies start connections in Settings > Connected apps.
The sandbox
- Every integration gets its own sandbox: a complete Lovelio agency seeded with realistic data - clients, jobs, candidates with CVs, a live pipeline, interviews and placements - plus one API key with full scopes.
- The sandbox is a real Lovelio tenant on the US region. The API behaves exactly as it does for a paying agency: same endpoints, same webhooks, same permissions, same rate limits. The portal shows the API base URL for its environment. Staging uses the staging API.
- Sandboxes can never send email to anyone and never appear in the marketplace, by construction. Test freely.
- Setup saves progress as it works. Reloading or returning to the integration resumes an interrupted setup in the same agency.
- The API key appears when it is issued. Replace API key revokes the previous portal key and keeps the agency and all its data. Reset sandbox is a separate, confirmed action that wipes the agency.
- After that one-time reveal the portal shows the first 20 characters of the key with the rest masked out. It identifies the key; it will not authenticate a request. The portal does not reveal a saved key again. Lovelio stores a protected copy for certification and recovery. A lost key means choosing Replace API key, which keeps the data. Client secrets are stored as hashes and revealed once. Rotate issues a new secret; it requires fresh certification and review.
- Sandboxes do not expire. They stay until reset by the developer or removed by Lovelio.
- "Open sandbox" uses a one-time link tied to the same browser to sign in to the sandbox agency in a new tab - that is how they see their own consent screen, the Connected apps page, and the data their integration writes. The developer session stays signed in. If the browser blocks the new tab, use Open sandbox in this tab.
Webhooks
- Create webhook subscriptions against the sandbox with POST /api/v1/webhooks. The portal shows a live view of every subscription and recent deliveries, including response codes and retries.
- Every delivery, retry and test requires an active subscription and connection, a public destination, and a working HMAC-SHA256 signing secret. Redirects are refused. Database or signing failures never send unsigned data. Up to seven attempts share one counter across workers.
- Payloads are HMAC-SHA256 signed. The full event catalogue is at GET /api/v1/webhooks/events, and the webhooks guide under /docs/agents/webhooks covers signature verification.
- Sandboxes really deliver webhooks to the developer's endpoints (they are the one demo-class tenant that does); email from a sandbox stays permanently muted.
The connect flow (OAuth apps)
- The client ID and client secret are a DIFFERENT credential from the sandbox API key, and a developer building a real app needs both. The API key (sk_test_...) is a Bearer token for the developer's own sandbox agency and nothing else - it is the right credential for a test script. The client ID + secret are an OAuth client: they are how OTHER agencies connect the app, and they yield access tokens (lc_at_...) scoped to what each agency granted. Lovelio mints the client ID and secret when the integration is created, so "where do I get a client ID?" is answered by the Keys and callback panel.
- Each integration has one OAuth client: a client ID (lc_client_...) that is safe to publish and a client secret (lc_secret_...) shown exactly once, with a Rotate button in the Keys and callback panel if it leaks. The same panel holds the two ends of the connection, together because both are a route on the partner's own server that nobody looks at: the CONNECT ENDPOINT (where Lovelio hands off when a signed-in agency starts a connection, and which redirects straight back to the Lovelio approve screen) and the REDIRECT URIs (where /api/oauth/authorize sends them back; HTTPS, or HTTP on localhost, 127.0.0.1 or [::1] for development; the exact path, port and trailing slash must match). A localhost or loopback callback is fine while building; step 2 warns that it is registered so the developer remembers to add the real one before agencies connect. The checks fetch both links, skip a localhost one, and fail on a 404 or a dead domain. An app can never request full access (admin) or the key-minting scope (accounts:write).
- Agencies connect the app through a standard OAuth authorization-code flow with PKCE: the app sends an admin to /api/oauth/authorize on the agency's region domain, Lovelio shows a consent screen ("AppName wants access to AgencyName" with the scope list in plain words), and the admin approves or cancels. Connecting and disconnecting need admin access (the integrations permission); other roles are told to ask an admin.
- The developer does not have to write that flow, or even read it. Step 2 leads with ONE button, "Copy setup prompt": a single self-contained prompt for the developer's own AI coding tool, carrying the mental model (agencies click Connect and never leave Lovelio), the app's real client ID, redirect URI and region, the Node reference implementation as the contract, and the rules that bite (exact redirect URI match, rotating refresh tokens, reading the granted scope). The tool builds both routes in the developer's own stack. The prompt never contains the client secret - the developer pastes that into their env file themselves.
- A developer not using an agent follows "I am not using an agent" in step 2 to /docs/connect-flow, a plain server page (readable with curl) that prints the flow as working source with placeholders: a connect route and a callback route in Node, Python, PHP, Go and cURL, plus the four env values. The portal itself no longer prints code. The four values the code reads (LOVELIO_API_URL, LOVELIO_CLIENT_ID, LOVELIO_CLIENT_SECRET, LOVELIO_REDIRECT_URI) appear as one ready-made .env block at the moment the secret is issued, because that is the only moment the secret exists in a browser; the Keys and callback panel prints the block again with the secret left blank. The prompt updates live as the developer changes the callback or scopes.
- The samples, the OpenAPI spec's appOAuth2 security scheme, the RFC 8414 discovery document and the OAuth routes themselves all read one module, lib/connect/connectFlow.ts, so a sample can never describe a flow the server does not serve.
- Approving creates the connection and hands the app tokens scoped to exactly what was approved. Access tokens last an hour; refresh tokens rotate on every use and keep working while the integration stays active. Scope enforcement is real: every V1 request made with an app token is checked against the granted scopes.
- Before approval, an app can only connect to its own sandbox agency - that is how developers test the whole flow. The consent screen labels it as a Sandbox connection while the developer portal session remains separate. Once approved, any Lovelio agency can connect to it.
- Access is NOT picked off a checklist. The creation form takes one sentence saying what the product does, then two questions - does it write anything back into Lovelio, and does it show or calculate fees, salaries or commission. Lovelio works out the minimal access from those answers and switches it on. Answering "no, it only reads" bars every write outright. Removing access is free; adding something the answers did not call for takes a written sentence saying why, and that sentence is shown to the reviewer AND to every agency on the approve screen.
- A note, call or document your code puts onto one record (a placement, a candidate) is covered by that record's write access, and reading a record's documents or activity is covered by its read access; Activities and Documents access are only for handling notes or files as such across every record type. If your code is refused for missing access while testing in the sandbox, the app's page in the portal shows the refused call in a pink alert ("Your code called POST /api/v1/activities, which needs ...") with an Open Access button; add the access, then connect the app again in the sandbox so the new token carries it. Adding access after approval sends the app back to review.
- The access list is shown in plain English ("Placements - read", "Documents - write"), and only the areas the integration actually uses. Everything else is behind "Ask for something else", and the technical scope names are behind a "Technical names" disclosure for developers who want them.
- The same answers cannot be re-submitted for a different result: the derivation is keyed to a hash of the text, so identical answers always give identical scopes. Changing the answers re-derives.
- What the agency sees when connecting changed with it: the approve screen now leads with the developer's own description of the product, then lists each scope with the reason it was granted. Anything asked for beyond the description is flagged in amber with the developer's justification underneath.
- Traffic is measured per resource, not just counted. Lovelio records which records a connected app reads and writes, so an agency can see on Settings > Connected apps exactly what each app has been using - "placement fees and salaries: read 4,000 times in the last 30 days". Money is reported on its own line and never folded into its parent record type.
- The same measurements flag drift on an approved app: a scope it holds but has never called in 30 days, a write path it said it uses and never has, or an app that answered "no" to the money question and then reads money. These are advisory - nothing revokes itself, because a seasonal integration is not a bad actor - but they show on the developer's own telemetry and in Lovelio's admin review. Lovelio's review desk and Migration Magic console are owner-only inside Lovelio admin: Brett alone can open them, so review decisions and migration launches always come from one person.
- Answering yes to "Does your product show or calculate fees, salaries or commission?" switches on placement money (placements:financials:read) for every placement the product reads; answering no forbids every money scope, whatever the product sentence says. The client fee schedule and split-fee deal money are only derived when the product sentence names them.
- The three money scopes (placements:financials:read, clients:financials:read, marketplace:financials:read) are always elevated tier, whatever else the app asks for: a human reviews the app and it starts at the lowest rollout cap. An app that only needs to know a placement happened should not tick them - it still gets the placement, the candidate, the client, the dates and the status without them.
- Nothing locks while the app is in review. The developer can keep editing the listing, the keys, the callbacks and the access; each edit is logged as made during review so Lovelio looks again before deciding. Only a rejected app is read-only. ADDING scopes to an approved app forces re-review: it comes off the directory and back to draft until it is re-certified and resubmitted. REMOVING scopes is free - the app stays approved and listed. Agencies that already connected keep the scopes they granted either way.
Connected apps (Settings > Connected apps)
- The agency-side view of connected partner apps. Each card shows the app, who built it, when it was connected, what it can do in plain words, and how many webhook subscriptions it holds.
- The same page is where a connection starts: a "Connect an app" section lists every approved partner app with who built it and what it does. Clicking Connect leads straight to the approve screen, which shows exactly what the app can access before it gets anything. Apps already connected show a Connected marker instead of the button. Connecting needs admin access (the integrations permission), the same as disconnecting.
- Disconnect cuts the app off immediately: its credentials and tokens are revoked and its webhook subscriptions are disabled. Disconnecting needs admin access.
- Keys minted by app connections do not appear under Settings > API keys - the Connected apps page is their home.
Certification
- The platform diagnostics are information for the developer and the reviewer, never a gate. There is no button to start them: once Lovelio has seen the partner's code do the connect flow against the sandbox, the checks start on their own (from the portal, or a scheduled sweep) and step 2 shows the step-by-step report under "Lovelio's own checks", with Run checks again for a red run. They run against the developer's own sandbox.
- The webhook check uses the signing secret returned when it creates its test subscription. It removes that subscription after the check, including when the check fails. If removal fails, the report identifies the webhook to remove before another run.
- Platform diagnostics check authentication, errors, pagination, Lovelio's signed webhook sender and the internal sandbox connection path. These are not proof of the partner's callback or webhook receiver.
- Seen in your sandbox is the second half. Lovelio serves the consent screen, the token door, the API and webhook delivery, so it logs the moment the partner's real code does each step against the sandbox. The required set is the happy path only: consent completes and the code is exchanged, then one API call works with the app token. Apps with a write scope also need one write to land; apps with webhooks:write need one signed delivery answered with a 2xx. Nobody is asked to fail on purpose: a refused bad exchange, a refused scope, a refresh and a revoked token are Lovelio's own behaviour and gate nothing. Each line reads Seen with the time, or Not yet seen, and step 2 sums them as "Lovelio has seen N of M things your code needs to do". Nobody can tick one by hand, a hosted demo does not count, and an unseen line never switches Request approval or Approve off.
- When a partner's code asks the authorize door for a scope the app does not have, Lovelio refuses the connect attempt and says so in two places: the redirect back to their callback carries error=invalid_scope with an error_description naming the missing scopes, and step 2 of the developer portal shows "Refused a connect attempt: your code asked for X, which this app does not have" with a button to Access. The fix is either adding the scopes in Access or changing the scope the code sends. Before 2026-09-05 this refusal was silent from the portal, which read as "it's not connecting".
- Link checks prove reachability only. HTTP 500 and other server failures need a fix or a retry. A bare callback may correctly return 400 without parameters. Localhost and private destinations remain Not checked. Nothing in the report blocks submission or approval; a hosted demonstration cannot prove partner readiness, so the reviewer reads the report and decides.
- Changing the OAuth secret, connect endpoint or redirect URIs of an approved app returns it to draft for fresh review.
- Certification, sandbox operations and scope derivation have workspace limits. If the counter is unavailable, retry later.
- A green run goes stale if the sandbox is reset, the OAuth client or secret changes, the scope set changes, or either of the two links changes afterwards - the checks run again on their own and the reviewer sees the newest result.
- The report is attached to the submission, so the reviewer reads it next to the listing.
- Approval is a person's decision (since 2026-09-05). The review desk shows what Lovelio saw (the diagnostics, the sandbox lines, the refusals, the usage) as information next to the listing, and nothing it saw switches Approve off. Approve refuses only an app that is not submitted, is suspended, or changed since the reviewer loaded it. Changing a secret, redirect URI or scope starts the sandbox log again for the new configuration.
- A green platform result alone never claims the partner callback or webhook handler worked; only Lovelio seeing it in the sandbox does. The reviewer reads both and decides.
Submitting for review
- Request approval needs exactly two things: a name and one sentence an agency owner would understand. Nothing else is required, because a directory entry cannot exist without those two and can exist without everything else. Category, connect address, logo, screenshots, support and privacy links make the listing better and can come later, including while it is in review. Lovelio never invents a support or privacy link; a blank one stays blank for the developer to fill. The tagline, terms link and website link are optional - a blank tagline falls back to the first sentence of the description.
- /api/oauth/authorize refuses any redirect_uri that is not registered, so an approved app with no real callback cannot be connected by any agency. That is a reason for the reviewer to ask for changes, not a rule that switches a button off; Lovelio registered a placeholder callback at creation and step 2 says when only a localhost one is there.
- Lovelio reviews every submission by hand and replies by email: approved, changes requested (with the reason), or rejected (with the reason). Changes requested shows the note on step 4 and on the app list; the developer fixes it and sends it again.
- The app list and the steps read the same state. A requested-change note takes priority in both; returning to the list refreshes it.
The public integrations directory
- The directory at lovelio.ai/integrations shows Lovelio's own integrations (Slack, WhatsApp, calendars, job boards and so on) alongside every approved Lovelio Connect app. Approval puts an app in the directory immediately; suspending it removes it.
- Each Connect card shows the app name, who built it, its tagline and category. The public directory is discovery only: there is no Connect button on it or on an app's page, because connecting is for signed-in Lovelio customers - an agency admin connects from Settings > Connected apps inside the app. When a connection starts, the partner's connect endpoint redirects straight back to the Lovelio consent screen where the agency admin approves the scopes - the agency never sees a page of the partner's.
- Clicking a Connect card opens the app's own page at lovelio.ai/integrations/its-slug: the partner's screenshots and short videos (up to 3), their longer write-up (what it does, who it is for, why use it), links, and a "What it can access" list in plain English - the same access lines the consent screen shows.
- Listing TEXT (name, description, the longer write-up, category, tagline, support and policy links) stays editable in the portal after approval and publishes straight away, without re-review. MEDIA is different: new or changed screenshots and videos on an approved app wait for a quick Lovelio review before they go live; the page keeps the current media meanwhile. Before approval, media saves directly - the submission is reviewed as a whole.
- Adding scopes is the opposite: it forces re-review and pulls the app from the directory until re-approved. Removing scopes never costs review.
Operations: rollout caps, telemetry, and the kill switch
- Review runs in risk tiers, derived from the scopes an app requests: low (read-only), standard (writes), elevated (email content, candidate documents, or marketplace writes). The tier is shown in the review queue with the scopes that caused it.
- Approval starts every app in a limited rollout: a cap on active connections, seeded from the risk tier (low-risk apps get a high cap, elevated-risk apps a low one). An agency trying to connect past the cap sees an "app at capacity" page instead of the consent screen; the partner asks Lovelio to raise or remove the cap as the app proves out. Sandbox connections never count against it.
- The portal shows a Usage card per integration, three numbers never one: the partner's own build and test calls against the sandbox, calls made through connected agencies, and webhooks delivered to them, over 30 days and across every region. Lovelio's own traffic (certification runs and any Lovelio testing) is a separate grey line on the card and is never added to the partner's numbers. Counts only - partners never see which agencies connected.
- Efficiency is advisory, never a gate: when an app reads more than 5 records for every write, the Usage card and the review desk show a "watch" note with the top resources read and a nudge towards webhooks. It never blocks submit or approval.
- What the partner's real integration was seen doing against the sandbox (consent, an API call, a write, a webhook) rides along to the review desk as a count and a dated list. It is never a gate on Request approval: a reviewer who sees "1 of 4 seen" reads the report and decides, and can ask for changes.
- Suspending an app is the kill switch: it comes off the directory, new connections and OAuth stop, and every existing connection stops working at once - API credentials refused and webhook deliveries halted, in every region. Unsuspending restores the connections exactly as they were; the sandbox key stays revoked until the partner replaces it. Their sandbox data stays.
Docs for developers
- API reference: /docs/api (the live OpenAPI spec), or /docs/api.md for the same thing as plain markdown an AI agent can read in one fetch.
- Agent guides, webhooks, error handling and SDKs: /docs/agents.
- Complete reference-check recipe: /docs/agents/reference-checks.
- The Lovelio MCP server for AI agents: /docs/mcp.