Help · Developers and apps
Build an app and list it in the KudosCRM Marketplace
Turn your product into a KudosCRM app that any workspace can install. Become a developer from a free workspace, accept the partner agreement, create the app, set up OAuth, scopes, webhooks and the listing, test it, send it to review and release it to the Marketplace. Every screen, limit, endpoint and error, in order.
Updated October 2026
Any KudosCRM workspace admin can build an app that other KudosCRM workspaces install. You become a developer from your own workspace, build the app in the developer console at app.kudoscrm.com/developers, and send it to KudosCRM for review. Once KudosCRM approves it, you release it, and it appears in the Marketplace of every KudosCRM workspace. Becoming a developer and listing an app are free.
This guide follows a developer from the first click to a listed app. The examples use a made-up company, Acme Telecom, and its app, Acme Dialer, on example.com domains.
Watch the video

Chapters: 0:24 Create your account · 1:16 Become a developer · 2:24 Create your app · 3:46 Scopes and a test install · 5:09 Events, listing and submit · 6:34 Release it · 7:22 A customer installs it · 8:23 Where to go next.
At a glance
| Question | Answer |
|---|---|
| Who can build | Any admin of a KudosCRM workspace. The free plan is enough. |
| Cost | Free. Becoming a developer is free, and listing an app in the Marketplace is free. |
| Where you build | The developer console: https://app.kudoscrm.com/developers |
| The steps | 1 Become a developer · 2 Accept the partner agreement · 3 Create the app · 4 Fill in the editor tabs · 5 Install it in your own workspaces and test · 6 Submit for review · 7 Release |
| How installs work | OAuth 2.0 authorization code with PKCE (S256). The customer's admin approves your app on a consent screen. |
| How you get events | Signed webhooks (Standard Webhooks headers), with a signing key for each install. |
| Starter limits | 5 apps and 5 test workspaces until KudosCRM approves your first app. Removed test workspaces still count. |
| Review | KudosCRM reviews every app and every new version before it is listed. The console says review usually takes up to 5 business days. |
| Where a listed app appears | Settings › Marketplace in every KudosCRM workspace, its own listing page, and kudoscrm.com/integrations after the next website build. |
| Developer docs | https://app.kudoscrm.com/docs/build-an-app/ |
What you can build
An app is your product, connected to KudosCRM. A customer's admin installs it into their workspace, and from then on your app can read and write that workspace's data within the access the admin approved. Examples: a phone system that logs calls on the right contact, a billing tool that keeps companies in sync, or a booking tool that adds meetings to the timeline.
The console's sign-up page lists what every developer gets:
- OAuth 2.0 installs: workspaces install your app through a consent screen their admin reads and approves.
- Signed webhooks: CRM events delivered to your server, signed with a key for each install.
- REST API: contacts, companies, deals, activities and more, within the scopes each install grants.
- A marketplace listing: in every workspace's marketplace and on kudoscrm.com, once KudosCRM approves your app.
Building a calling or SMS app? Pick the Telephony v1 contract. KudosCRM then turns your call events into call activities, missed-call tasks and voicemails with no custom code on either side.
Only need your own workspace?
If only your own workspace will use what you build, you don't need an app. An API token and an outbound webhook are simpler. See API tokens and the REST API. An app is for a product that many workspaces install.
Who can be a developer
- Any admin of a KudosCRM workspace. The free plan is enough. That workspace becomes your company's developer workspace (the docs call it the home workspace). You build and test from it.
- One workspace, one company. A workspace can be the developer workspace of only one company. To build as another company, use that company's own workspace.
- Your team. Every admin of the developer workspace who has the Build, submit & release developer apps permission is a developer of your company. Admins have it by default. They appear in the console under Team.
- Members who are not admins can't set this up. They see “An admin of this workspace can set this up”.
If you don't have a KudosCRM account yet
- Open the developer console
On kudoscrm.com/integrations, find Build an App for the KudosCRM Marketplace and click Start Building. Or go straight tohttps://app.kudoscrm.com/developers. If you are signed out, KudosCRM shows the sign-in page and remembers that you were going to the developer console. - Create an account
On the sign-in page, click Create an account (next to “New here?”). On Create your account, enter your first name, last name, work email and a password, tick the terms box, and click Create account. You can also click Sign up with Google. - Verify your email
On Verify your email, enter the 6-digit code KudosCRM emailed you. It expires in 15 minutes. Click Verify email. Until you verify, your workspace is view-only, so verify before you continue. - Land on the developer console
After verifying, you land back on/developers, on the page Build apps for KudosCRM. Continue with the next section.

Become a developer
- Open the developer console from your company's workspace
Sign in and switch to the workspace your company will build from. Go tohttps://app.kudoscrm.com/developers. The page is titled Build apps for KudosCRM, with four cards under What you get and a box called Become a developer. - Enter your company name
In Company name, type your company's name, for exampleAcme Telecom. It is shown on your listings as the app's developer. Up to 80 characters. - Enter your website
In Website, type your company's site, for examplehttps://www.example.com. If you type only a domain, KudosCRM addshttps://. Your company claims this site's domain (www.example.comclaimsexample.com). Your app's redirect URLs, install page, app URL and help article URL must sit on that domain or a host under it. KudosCRM verifies the domain during review. - Enter your support email
In Support email, type where customers write for help with your apps, for example[email protected]. - Read the three notes
Under the fields, the box says: new publishers can have up to 5 apps and 5 test workspaces until KudosCRM approves their first app; every app and every version is reviewed before it's listed, and until then it installs only in your own workspaces; and you'll accept the partner agreement before your first submission for review. - Click Become a developer
A message confirms “Acme Telecom is set up — Create your first app to get started.” The console opens on My apps.

My apps is the console's home. The left menu has My apps, Analytics, Test workspaces, Logs, Team and Partner agreement. Under the menu, a card shows your company and whether its domain is verified yet. A line under the first box counts your apps against the starter limit, for example “0 of 5 apps while KudosCRM hasn't approved your first app yet. The limit lifts with that approval.”

When Become a developer is refused
| What you see | What it means | What to do |
|---|---|---|
| “An admin of this workspace can set this up” | You are a member, not an admin, of this workspace. | Ask an admin to become a developer here, or to make you an admin. |
| “{Workspace} is already a developer workspace” | Someone already made this workspace a developer workspace. | Ask an owner of the workspace for developer access (admin role). |
| “Your apps are in another workspace” or “You build apps in another workspace”, with Switch to {name} | You are already a developer in another workspace. | Click Switch to {name}. If the form also shows, you may make this workspace a second company's developer workspace. |
| “Partner access is by invitation” | KudosCRM has paused open sign-up for now. | Click Request access to email KudosCRM, which can invite your company. |
| “Support can't do this for the customer” | Someone from support is signed in as you. | Sign in as yourself and try again. |
| “That's KudosCRM's own name. Enter your company's name.” | Names that read as KudosCRM or Saanverse are reserved. | Use your own company's name. “Kudos Bakery” is fine. |
| “That's a KudosCRM website. Enter your company's own website.” / “That's a KudosCRM address…” | The website or support email is on a KudosCRM domain. | Use your company's own website and email. |
| “{domain} is verified for another KudosCRM publisher. Enter your own company's website.” | Another company already verified that domain. | Enter your own company's website. If the domain is yours, contact KudosCRM support. |
Accept the partner agreement
The partner agreement is the contract between your company and Kudos for apps in the Marketplace. It is a clickwrap: you read it in the console and tick a box. You can build without it, but Submit stays blocked until your company has accepted the version in force. When Kudos publishes a new version, your company accepts it again before its next submission.
- Open the agreement
Click Partner agreement in the left menu, or Read the agreement on My apps. The page is titled Partner agreement. Under the agreement's title you see its version and date, for example “Version 2026-10”, and a Download PDF link when one is available. - Read it, then tick the box
Tick “I have read and agree to the KudosCRM Partner Agreement on behalf of Acme Telecom”. - Click Accept
A message confirms “Partner agreement accepted — You can send apps to review now.” The page then shows who accepted it, when, and which version.

- If the text changed while the page was open, KudosCRM says “The Partner Agreement changed while this page was open. Read the new version above, then accept it.” Tick the box again and click Accept.
- When a new version is published, a banner says “A new version of the Partner Agreement needs your acceptance before your next submission.”
Create an app
- Click Create app
On My apps, click Create app. The page Create an app asks for a name, a key and a category. - Name it
In Name, type the name customers will see on the Marketplace card and listing page, for exampleAcme Dialer. You can change it later. Up to 80 characters. - Choose the key, carefully
KudosCRM suggests a Key from the name, for exampleacme_dialer. The key is permanent. It becomes your client id (app_acme_dialer) and the name your records carry in KudosCRM. Use 2–60 lowercase letters, digits or underscores, starting with a letter. Put your company's name in it. Built-in app keys and well-known brand names are reserved (for exampleslack,salesforce,hubspot,zoho,pipedrive,google,microsoft,whatsapp,meta,twilio,stripe,zoom,calendly,mailchimp), and so is any key starting withkudos. - Pick a category
Open Category and pick one, for example Calling & SMS, Email & calendar, Messaging & chat, Meetings & video, Payments & billing, Automation, Ads & analytics or Data & migration. - Click Create app and store both secrets now
The page changes to “Acme Dialer is created”. It shows the client id and says the app starts as a private draft, version 1.0, that installs only in your company's workspace. It shows two secrets once: the Client secret (startskcs_; your server sends it with the client id to exchange codes and refresh tokens) and the Signing secret (startswhsec_; each install's webhook key is derived from it). Copy both into your server's secret settings. - Confirm and open the app
Tick “I have stored both secrets. I understand they can't be shown again.” and click Open Acme Dialer. The app editor opens on its Auth tab.
The secrets are shown once
KudosCRM keeps only a fingerprint of each secret. If you lose one, rotate it from the app's Auth tab to get a new one. If you try to leave the page before storing them, KudosCRM asks “Leave before storing the secrets?”.

Fill in the app editor, tab by tab
The editor has seven tabs down the left: Basic info, Auth, Scopes, Events, Listing, Test and Submit. Each tab shows a green check when it has everything review needs, or “N to do” while it doesn't. The button at the top right shows what is left: Finish setup (N) takes you to the next tab with something to do, and becomes Submit v1.0 when nothing is left. Beside it, a short line shows the state of the automated checks, for example “Checks not run yet” or “4 of 6 checks pass”.
Everything you fill in here is the app's working copy: the version KudosCRM reviews. When you change a field, a bar at the bottom says “Unsaved edits on …”. Click Save to keep them, or Undo edits.
Basic info
- Name: the name on the Marketplace card and listing page.
- Publisher: your company. It can't be changed here.
- Category: where the app sits in the Marketplace.
- Website, Privacy policy URL and Terms of service URL: all three are needed to submit. Use full
https://URLs. - Support email: needed to submit unless you give a help article URL. Reviewers check that it reaches a person.
- Support response time: optional, for example “Replies within 1 business day”. Shown on the listing's Support tab.
- Help article URL, App URL (where “Open Acme Dialer” goes from an installed app) and Install URL (where the Marketplace's Install button sends admins to start the connection). These three must be on your domain or a host under it, for example
https://app.example.com/integrations/kudos/install. The line above them says so: “Help article, app and install URLs must be on example.com or a host under it. KudosCRM verifies your domain during review; until then your app can't be listed.” - More options › Internal name (optional): a name only you and reviewers see. Leave it empty to use the name above.

Auth
- Check your client credentials
The Client credentials card shows the Client ID (with a copy button), and the Client secret and Signing secret masked, each with a Rotate button. The client secret shows itskcs_start and its last four characters, so you can tell which one your server holds; the signing secret showswhsec_. “Secrets are shown once, when they are created or rotated. KudosCRM keeps only a fingerprint.” - Rotate a secret if you lost it or it leaked
Click Rotate beside the secret. Under “Keep the old one working for”, choose Stop it now, 1 hour or 24 hours. During that time both the old and the new secret work, so you can deploy the new one without dropping a request. The new secret is shown once. Every developer on your team gets an email when a secret is rotated. - Add your redirect URL
Under Redirect URLs, click Add URL and enter the URL on your server that receives the authorization code, for examplehttps://app.example.com/integrations/kudos/callback. It must usehttps://and sit on your domain or a host under it. You can add up to 10. The authorize step sends people back only to a URL on this list. Each URL in the list has a pill: Domain not verified until KudosCRM verifies your domain (it doesn't stop you saving or submitting), then Verified domain. - Use “Test workspaces only” for local development
Tick Test workspaces only to add a URL on another host, such ashttp://localhost:3000/callbackorhttp://127.0.0.1. Such a URL works only when installing in your company's workspace and your test workspaces. Its pill reads Test workspaces only. - Copy the endpoints
The Endpoints card lists the authorize (GET https://app.kudoscrm.com/oauth/authorize), token (POST https://api.kudoscrm.com/oauth/token) and revoke (POST https://api.kudoscrm.com/oauth/revoke) URLs, each with a copy button, and says: “Standard OAuth 2.0 authorization code with PKCE (S256). Access tokens last 1 hour; refresh tokens rotate on every use, so most OAuth client libraries work unchanged.”

About your domain
Your domain is claimed when you sign up and verified by KudosCRM during review. While it is only claimed, you can save and submit URLs on it. A URL on any other host is refused with “The host must be example.com or sit under it. Mark it test-only to use another host.” Nothing can be listed in the Marketplace until KudosCRM has verified the domain.
Scopes
Scopes are the access your app asks for, such as contacts:read (“Contacts and leads”) or tasks:write (“Tasks”). The admin reads them on the consent screen. The tab opens with “Ask for the least you need. Your reason is shown to admins on the consent screen.” The full list is under Scope catalog at the top right (/developers/scopes). The table has four columns: Scope, Request, Why your app needs it and Sensitivity.
- Choose Required, Optional or Off for each scope
Required: the app can't work without it. Optional: the admin sees a switch on the consent screen and may turn it off. Off: not requested. The scopes you request are listed first; the ones you don't fold under a link with their count, for example More scopes (12). If your app uses the Telephony v1 contract (see Events), a line under the intro says “The telephony contract keeps contacts:read, users:read, activities:write and tasks:write on Required.”, and those four are locked on Required. - Give a reason for each scope
In Why your app needs it, say what your app does with it, in up to 140 characters, for example “Match each caller to a contact or lead so the call lands on the right record.” Every requested scope needs a reason before you can submit. Admins read it on the consent screen. - For optional scopes, write the switch text
Under the reason of an optional scope, click Consent switch · on by default (or · off by default) to open it. Choose whether it is On by default, and write what admins read when it is on (“When on: what your app does with it”) and when it is off (“When off: what happens instead”). For example, forleads:write: “Calls from unknown numbers create a new lead.” and “Calls from unknown numbers stay in the Unmatched calls list.” As the panel says, “Admins see this switch, and these sentences, on the consent screen.”
Each row also shows the scope's sensitivity, for example Personal data or Standard. Write access never includes read access, and no scope lets an app delete records.

Events
The Events tab has two cards: Events your app sends at the top, then Events your app receives.
Events your app sends is where you pick a contract (“Pick the category contract you implement. KudosCRM maps it — no custom code on either side.”). In Contract, choose None — REST only if your app only calls the REST API. Choose Telephony v1 for a calling or SMS app:
- It requires the scopes
contacts:read,users:read,activities:writeandtasks:write, and may ask forleads:writeas optional (so unknown callers can become leads). Picking the contract sets the four to Required for you and locks them there on the Scopes tab. - The card then lists every event in the contract, each labelled Required, If supported, Off by default or Flags only. The four required events,
call.started,call.answered,call.missedandcall.logged, are ticked for you and can't be unticked. Tick the others your product supports, such ascontact.match,voicemail.received,sms.received,recording.readyandtranscript.ready. - If a saved copy is missing a required event, the card says “Telephony v1 apps send … Tick them below before you submit.” Click Add them.
- Read the telephony contract, under the list, opens the full contract at
/developers/blueprints/telephony.
Events your app receives are the KudosCRM events sent to your server, such as contact.created or deal.stage_changed. Once you've entered a URL, the card says “Delivered to … signed with Standard Webhooks.” The full list of events, with every field and an example, is at /developers/events.
- Enter your webhook URL
In Webhook URL, enter the URL that receives the events. Put{install_id}where each install's public id goes, for examplehttps://api.example.com/kudos/webhooks/{install_id}. It must be a public address KudosCRM can reach: its host has to resolve on the public internet when you save, or the save is refused (see Troubleshooting). - Say why you want the events
Fill in Why your app wants these events, in up to 140 characters. - Tick the events
Events are grouped by object, for example Contacts · 2 of 4. Tick each event your app uses, and say in the box that opens under it what your app does with it. An event needs the matching read scope (for examplecontact.*needscontacts:read). If you tick one whose scope you don't request, the tab offers Request contacts:read right there.

Listing
The Listing tab is what customers see in the Marketplace. A Marketplace card preview on the right updates as you type.
| Field | What to put | Limit |
|---|---|---|
| Tagline | The one line on the Marketplace card. Needed to submit. | 110 characters |
| Description | Plain text. A blank line starts a new paragraph. Needed to submit. | 4,000 characters |
| Price label | Your own plans: Free, Free and paid plans available, or Free to install · needs a {app name} plan. Listing on KudosCRM is free. | One choice |
| Logo | Click Upload logo. Square PNG, JPEG or WebP, at least 256 × 256. Needed to submit. | 2 MB |
| Screenshots | Click Add. 16:10, at least 1600 × 1000, PNG, JPEG or WebP, each with an optional caption. | Up to 6, 5 MB each, caption 60 characters |
| What it does | Highlights, each with a short title and one or two sentences. Click Add highlight. | Up to 4 |
| How it works | Three steps from install to the first result. Click Add step. | Up to 3 |
| What syncs, and which way | What lives in your app, which way it moves, and where it lands in KudosCRM, for example Calls → Call activities. Click Add a row. | Up to 6 rows |
| Setup guide | The steps an admin follows, in order. Shown on the listing's Setup guide tab. Click Add a step. | Up to 8 steps, 200 characters each |
SVG and GIF images are refused. The logo and screenshots belong to this version: they are reviewed with it and go live when you release it.

Test your app before you submit
A new app is private: it installs only in your company's developer workspace. To try it in other workspaces, add them as test workspaces.
- Add test workspaces (optional)
Click Test workspaces in the left menu, then Add workspace. In Add a test workspace, pick one of the workspaces where you are an owner or admin. It must be another workspace, not your developer workspace. A test workspace is an ordinary workspace with its own data, plan and settings, so use one with test data. The page lists your test workspaces with the columns Workspace (with its plan under the name), Apps installed and Added, and an Open button and a delete button on each row. Under the list, a line counts them against the starter limit, and the card How test workspaces work sums up the rules. - Choose where the app installs
In the app editor, open the Test tab. Below Automated checks is the Where it installs card: “Until a release lists it, the app installs only where you say, through the real consent screen.” Choose Acme Telecom's workspace or Test workspaces too. This is saved at once. Manage test workspaces opens the Test workspaces page. - Install your own working copy
Start the install from your product, the way a customer will: your install page sends you to the KudosCRM consent screen (see “Connect a workspace with OAuth 2.0” below). On the consent screen, if you belong to several workspaces, pick your developer workspace or a test workspace under Workspace, then click Allow and install. Versions that aren't released yet, and redirect URLs marked test-only, work in these workspaces. Submitting a version for review doesn't stop your team installing it. - Use the app for real
Install, make some API calls, receive some events, then uninstall once. The checks read what really happened. - Run the automated checks
At the top of the Test tab, under Automated checks, click Run checks (later Run again). Each check reads Pass, Check, Fail, Not run or Running, with one line under it saying what KudosCRM saw, for example “1 install reached active in the last 30 days — the latest in Acme Telecom QA on 29 Oct.” or “v1.0 has no webhook URL, so there is nothing to sign.” Results are “Computed from your app's real installs and traffic in the last 30 days. Reviewers see the same results.” A summary line ends the card, for example “4 of 6 pass · last run 29 Oct 2026, 3:13 PM UTC”, and the Test tab shows how many checks are still to do.
The six checks:
- Install completes through the real consent screen
- Uninstall revokes tokens and the app gets 401 afterwards
- Webhook signatures verified on a test delivery: KudosCRM sends a signed
webhook.pingto your webhook URL, then the same ping with a wrong signature. Answer the first2xxand the second400or401. - Same event sent twice is applied once
- Honors Retry-After on 429
- Only requested scopes used in the last 7 days


Starter limits
- A new developer company can have up to 5 apps and 5 test workspaces until KudosCRM approves its first app.
- The limits lift by themselves when KudosCRM approves your first app. KudosCRM can also raise or lift them for your company if you write in.
- Until then, every test workspace you ever added counts, including ones you removed or no longer administer. Adding one back takes no new room.
- After that, the platform limits apply: 50 apps per company and 25 test workspaces.
Submit your app for review
- Open the Submit tab
Click Submit v1.0 at the top right, or the Submit tab. The tab is headed Submit v1.0 for review. Under Ready to send, each tab reads Done with a green check, or what it still needs, with a button to go there. Automated checks shows how many pass, for example “4 of 6 pass”, with a See checks button; it gets its check only when every check passes. Checks that don't pass don't stop you submitting, but reviewers see them. - Clear anything under “Before you send”
This box lists what blocks the submission, for example “Save your edits first — review sees the saved copy.” (click Save edits) or “Acme Telecom hasn't accepted the partner agreement yet.” (click Read and accept it). - Read the domain note, if there is one
If your domain isn't verified yet, a blue box above the form says “KudosCRM verifies your domain, example.com, during review. Until it's verified, your app can't be listed in the marketplace.” You can still submit. - Say what changed
In What changed, say what is new in this version and why (“Reviewers read this first. Say what's new and why.”). - Link an install video
In Install video URL, paste a Loom or YouTube link that shows the install, start to finish, and an uninstall. - Give reviewers a test login
Under Reviewer test account, enter a Reviewer username or email and Reviewer password for a test account in your app. Only KudosCRM reviewers can see them, after a security check, and they're deleted once review ends. Each new round needs them again. - Confirm and submit
Tick “I confirm the app follows the partner agreement and asks only for the data it uses.” (partner agreement is a link to it). Click Submit for review. A message confirms “v1.0 sent to review”.

While a version is in review, it can't be edited. The editor says “v1.0 is submitted and waiting for a reviewer, so it can't be edited until our reviewers decide. Review usually takes up to 5 business days.”
What KudosCRM checks in review
A KudosCRM reviewer reads your submission, the automated check results, a preview of your listing and consent screen, and a list of what changed since your last released version. They tick a checklist of seven items:
- Each scope is needed for what the listing says.
- Consent wording is plain and accurate.
- Privacy policy and terms load.
- Install video shows install and uninstall.
- Reviewer login works in the test workspace.
- Listing claims are true.
- Support contact answers.
During your first review, KudosCRM also verifies your domain. The reviewer then decides:
- Approve: the editor says “KudosCRM approved v1.0. Release it when you're ready…” and the button at the top becomes Release v1.0.
- Request changes: the editor says “KudosCRM asked for changes to v1.0: “…” Edit it and submit again.” The badge by the app's name reads v1.0 · changes requested, and the Submit tab shows a Changes requested box with the decision date and the reviewer's note. Fix what the note asks, save, and submit again. The reviewer fields are empty again, with the line “Enter the test login again: the one you gave last round was deleted when that review ended.” This starts a new round.
- Reject: the editor says “KudosCRM didn't approve this version: “…”” Editing starts a new copy.

Release your approved app
- Click Release v1.0
A dialog asks “Release v1.0?” and says new installs get v1.0 at once. - Choose where it goes
Under Where it goes, pick one: List it in the marketplace (“Every KudosCRM workspace can find and install it.”), Test workspaces only (your company's workspace and your test workspaces; it isn't listed), or Acme Telecom's workspace only (only your own workspace; it isn't listed). - Click Release v1.0
Once listed, the editor says “v1.0 is live in the marketplace.” and offers View listing. On My apps the row reads Listed · v1.0 · Public marketplace.

Every release needs your domain verified when the app has URLs on it, whether it goes to the Marketplace or to your test workspaces. KudosCRM verifies the domain during review. If it isn't verified yet, the release is refused with “Acme Dialer can't be released until KudosCRM verifies Acme Telecom's domain, example.com…”. Ask KudosCRM to verify it, then release again.
Once an app is public, only KudosCRM can take it off the Marketplace.
Where your app appears
- In every KudosCRM workspace: Settings › Platform › Marketplace shows your card in its category. Its listing page (for example Marketplace › Calling & SMS › Acme Dialer) shows your logo, name, “by Acme Telecom” and tagline, an Install button that sends admins to your install URL, a Visit example.com link to your company's website (from the Website field, without
www.), and your price label, for example “Free to install”. Its tabs are Overview, Permissions, Events, Setup guide and Support. For a Telephony v1 app, the Overview starts with a What you will see on a contact card: a sample call marked “Example”, showing only what your app says it sends (for example “Transcript attached”). Then come About Acme Dialer (your description), What it does, What syncs, and which way, How it works and Screenshots. On the right, Data access sums up what the app can see, can do and never does, with See every permission; Details shows the category, what it works with, plans and version; and Publisher links your website, privacy policy and terms of service and says your company is responsible for the app and its support. - On kudoscrm.com: your tile on kudoscrm.com/integrations and your own page there, built from the same app registry. They appear after the next website build, not the moment you release.
- After install: the customer manages your app under Settings › Connected apps, where they can pause, reconnect or uninstall it.

Release a new version
- Edit the app
Open the app from My apps and change any tab. A banner says you are editing a pending copy: the live version keeps running for its installs until the new version is approved. Scopes, redirect URLs and events are reviewed fields. - Submit it
Every version goes through review, the first and every one after it. A new logo and new screenshots are reviewed with the version and show in the Marketplace only after you release it. - Release it
New installs get the new version at once. If it asks for a scope an existing install never approved, that workspace's admin sees “Acme Dialer 1.1 asks for more access” on Connected apps. Nothing is revoked while they decide. If you dropped a scope, it leaves every install's grant.
Connect a workspace with OAuth 2.0 and PKCE
This is standard OAuth 2.0 authorization code with PKCE (RFC 7636). Only S256 is accepted. Any off-the-shelf OAuth library works. The discovery document lists every URL:
curl https://api.kudoscrm.com/.well-known/oauth-authorization-server
- Make a verifier and its challenge
The verifier is 43–128 characters of[A-Za-z0-9-._~]. Keep it, with a randomstate, on your server until the admin comes back.CODE_VERIFIER=$(openssl rand -base64 48 | tr -d '=+/' | cut -c1-64) CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=') - Send the admin to the consent screen
Your install URL redirects the admin's browser to:https://app.kudoscrm.com/oauth/authorize?response_type=code &client_id=app_acme_dialer &redirect_uri=https%3A%2F%2Fapp.example.com%2Fintegrations%2Fkudos%2Fcallback &scope=contacts%3Aread%20users%3Aread%20activities%3Awrite%20tasks%3Awrite%20leads%3Awrite &state=5f2c9d1e &code_challenge=$CODE_CHALLENGE &code_challenge_method=S256redirect_urimust match one of your redirect URLs character for character. Leavescopeout to ask for everything the version requests. You can never ask for more. - The admin approves
The consent screen says “Acme Dialer wants to connect to your KudosCRM workspace”, with “Published by Acme Telecom · example.com” under it. It shows who is signed in, with a Not you? link. Under Workspace, an admin who belongs to several workspaces picks one from a menu; an admin with only one workspace sees its name and their role instead, for example “Northwind Traders · You are the owner”. They see what your app “will be able to see” and “will be able to do” (one row per scope, with your reason), optional scopes marked Optional with a checkbox, and a Never: line (for example “delete records, or see deals, quotes, invoices or email content”). They click Allow and install or Cancel. The footer names the host they'll return to and says they can remove access any time in Settings › Connected apps, and that your privacy policy and terms apply to the data your app receives. For an app KudosCRM has reviewed, a line under the card adds “KudosCRM checked this app's identity and the access it asks for.” with a How app review works link. - Check what comes back
On allow, the browser returns to your redirect URL withcode(akac_…code, valid 10 minutes, single use), yourstateandiss. Check thatstateis yours andissishttps://api.kudoscrm.com. On cancel you geterror=access_denied. - Exchange the code for tokens
Send the client secret in HTTP Basic or in the form body, never both and never in the query string.
The answer hascurl https://api.kudoscrm.com/oauth/token \ -u "app_acme_dialer:$CLIENT_SECRET" \ -d grant_type=authorization_code \ -d code="$CODE" \ -d redirect_uri=https://app.example.com/integrations/kudos/callback \ -d code_verifier="$CODE_VERIFIER"access_token(kat_…, 1 hour),refresh_token(krt_…),scope,install_id(inst_…),workspace(id,name),ingest_urlandsetup_url. Store the tokens per install. - Send the admin to setup_url
It opens KudosCRM on the right workspace to finish setup. For a telephony app, that is where the admin matches your agents to their users and chooses what happens to unknown callers and missed calls. Until they finish, Connected apps shows Finish setting up. - Call the API
A token acts as the install's acting admin, inside the scopes granted. A missing scope answerscurl "https://api.kudoscrm.com/api/v1/contacts?filter[phone]=%2B15555550142" \ -H "Authorization: Bearer $ACCESS_TOKEN"403withcode: insufficient_scopeandmeta.required_scope. - Refresh before the hour is up
Refresh tokens rotate: every refresh returns a new one, and the one you sent stops working. Store the new one before you use the new access token. Refresh tokens last 90 days, renewed on each rotation.curl https://api.kudoscrm.com/oauth/token -u "app_acme_dialer:$CLIENT_SECRET" \ -d grant_type=refresh_token -d refresh_token="$REFRESH_TOKEN" - Revoke when a customer disconnects in your product
The install then needs reconnecting, and your webhook hearscurl https://api.kudoscrm.com/oauth/revoke -u "app_acme_dialer:$CLIENT_SECRET" -d token="$REFRESH_TOKEN"integration.disconnectedwithreason: revoked.

Never refresh the same token twice
Two refreshes of one token within 30 seconds are treated as a race: the second getsinvalid_grant(refresh_token_already_rotated) and nothing is revoked. Use the tokens the first refresh returned. A rotated token presented later is treated as stolen: the install's grant is revoked and the admin must reconnect. The same goes for an authorization code used twice.
Receive signed webhooks
When an admin installs your app, KudosCRM creates one webhook subscription for that install from your Events tab. You never create it, and the admin can't edit it. Each event arrives as a JSON envelope:
{
"event_id": "evt_4d88894b1eae8347dea3c548",
"type": "deal.stage_changed",
"occurred_at": "2026-10-08T10:42:18Z",
"tenant_id": "3f6a1c2e-8b4d-4e7f-9a10-5c2d8e7f6a31",
"install_id": "inst_7Hq2XcRm4P",
"payload_version": 2,
"origin": { "kind": "user", "id": "5e2b9d14-…" },
"data": { "deal": { … }, "from_stage": { … }, "to_stage": { … } }
}
Each delivery carries these headers. Verify one of the two signature schemes:
Content-Type: application/json
User-Agent: KudosCRM-Webhooks/1.0
X-Kudos-Signature: t=1791456139,v1=7697…0d2d
X-Kudos-Event: deal.stage_changed
X-Kudos-Delivery: evt_4d88894b1eae8347dea3c548
X-Kudos-Delivery-Attempt: 1
webhook-id: evt_4d88894b1eae8347dea3c548
webhook-timestamp: 1791456139
webhook-signature: v1,sYxoDmpF…L0dI=
The signing key. Each install has its own key, derived from your app's signing secret and the install's id: "whsec_" + base64(HMAC-SHA256(key = signing secret exactly as issued, data = "kudos-install-v1:" + install_id)). You store one secret per app, and a key for one install never verifies another install's deliveries.
Verify in Node (the Standard Webhooks headers). Verify the raw body, before any JSON parsing, and reject timestamps more than 5 minutes from your clock:
import crypto from "node:crypto";
export function installSigningKey(appSigningSecret, installId) {
const digest = crypto.createHmac("sha256", appSigningSecret)
.update(`kudos-install-v1:${installId}`).digest("base64");
return `whsec_${digest}`;
}
export function verifyDelivery({ rawBody, headers, appSigningSecret, installId,
now = Math.floor(Date.now() / 1000), toleranceS = 300 }) {
const id = headers["webhook-id"];
const timestamp = Number(headers["webhook-timestamp"]);
if (!id || !Number.isFinite(timestamp) || Math.abs(now - timestamp) > toleranceS) return false;
const key = Buffer.from(installSigningKey(appSigningSecret, installId).slice("whsec_".length), "base64");
const expected = crypto.createHmac("sha256", key).update(`${id}.${timestamp}.`).update(rawBody).digest();
return String(headers["webhook-signature"] || "").split(" ").some((entry) => {
const [version, signature] = entry.split(",", 2);
const given = Buffer.from(signature || "", "base64");
return version === "v1" && given.length === expected.length && crypto.timingSafeEqual(given, expected);
});
}
Verify in Python:
import base64, binascii, hashlib, hmac, time
def install_signing_key(app_signing_secret: str, install_id: str) -> str:
digest = hmac.new(app_signing_secret.encode(), f"kudos-install-v1:{install_id}".encode(), hashlib.sha256).digest()
return "whsec_" + base64.b64encode(digest).decode()
def verify_delivery(raw_body: bytes, headers: dict, app_signing_secret: str, install_id: str, tolerance_s: int = 300) -> bool:
msg_id, timestamp = headers.get("webhook-id"), headers.get("webhook-timestamp", "")
if not msg_id or not timestamp.isdigit() or abs(int(time.time()) - int(timestamp)) > tolerance_s:
return False
key = base64.b64decode(install_signing_key(app_signing_secret, install_id).removeprefix("whsec_"))
expected = hmac.new(key, f"{msg_id}.{timestamp}.".encode() + raw_body, hashlib.sha256).digest()
for entry in headers.get("webhook-signature", "").split(" "):
version, _, signature = entry.partition(",")
try:
given = base64.b64decode(signature, validate=True)
except (binascii.Error, ValueError):
continue
if version == "v1" and hmac.compare_digest(given, expected):
return True
return False
Prefer X-Kudos-Signature? It is t=<unix>,v1=<hex>: the hex HMAC-SHA256 of "<t>.<raw body>", keyed by the derived key string exactly as computed, whsec_ included. After you rotate the signing secret with a grace period, deliveries carry two signatures. Accept the delivery if any one matches.
Answering, retries and duplicates
| Your answer | What KudosCRM does |
|---|---|
2xx within 8 seconds | Delivered. Do slow work after you answer. |
408, 429, 5xx, a timeout or a network error | Retries: 6 attempts in all, after about 30 s, 2 min, 10 min, 30 min and 1 h (±25 %). A Retry-After you send is honoured, up to 2 hours. |
Any other 4xx, or a redirect | Dead-lettered at once, no retry. Redirects are never followed. |
410 Gone | Dead-lettered, and this install's subscription stops. |
- Deduplicate on
event_id. It is the same on every retry and every replay. An admin can resend any event from Manage › Activity log, and it arrives with the sameevent_id. - Ten dead letters in a row stop the subscription. The admin sees “Deliveries stopped after repeated failures” on Connected apps, and Retry resends them, oldest first.
- Your own writes never come back. An event your app caused is not sent to it.
- Lifecycle events.
integration.installedarrives after your first code exchange.integration.disconnectedarrives with areason:uninstalled,revokedorreauth_required. - Answer
webhook.ping. Verify its signature, then answer2xx, even though it isn't an event you subscribed to.
Sending events to KudosCRM (telephony apps): POST each event to the install's own ingest_url from the token response, with install_id in the body, signed with X-Kudos-Signature using the install's derived key. Each event is applied once, so you can resend safely. The full contract is at /developers/blueprints/telephony.
Limits and URLs
| What | Value |
|---|---|
| Developer console | https://app.kudoscrm.com/developers |
| Developer docs | https://app.kudoscrm.com/docs/build-an-app/ |
| Scope catalog · event catalog · telephony contract | /developers/scopes · /developers/events · /developers/blueprints/telephony |
| Authorize | GET https://app.kudoscrm.com/oauth/authorize |
| Token · revoke | POST https://api.kudoscrm.com/oauth/token · POST https://api.kudoscrm.com/oauth/revoke |
| Discovery | https://api.kudoscrm.com/.well-known/oauth-authorization-server |
| REST API base | https://api.kudoscrm.com/api/v1/ |
| Client id · secrets | app_<key> · client secret kcs_… · signing secret whsec_… |
| Token lifetimes | Code 10 minutes, single use · access token 1 hour · refresh token 90 days, rotates on every use |
| API rate limit | 2,400 requests an hour per install by default. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. |
| Webhook | Answer within 8 seconds · signature valid for 5 minutes · 6 attempts |
| Redirect URLs | Up to 10, https:// on your domain (test-only ones may be http://localhost) |
| Starter limits | 5 apps, 5 test workspaces until your first app is approved |
| Platform limits | 50 apps per company, 25 test workspaces |
| Logo · screenshots | Square, ≥ 256 × 256, ≤ 2 MB · 16:10, ≥ 1600 × 1000, ≤ 5 MB, up to 6 |
| Request log | Every request your tokens make, kept 30 days, under Logs |
Troubleshooting
| What you see | What it means | What to do |
|---|---|---|
| “Use 2–60 lowercase letters, digits or underscores, starting with a letter.” | The key's format is wrong. | Fix the key, for example acme_dialer. |
| “acme_dialer is already taken. Choose another.” | Another app uses that key. | Choose another key. |
| “zoom is reserved for a well-known brand. Choose a key with your company's name in it.” | Brand names and keys starting kudos are reserved. | Put your company's name in the key. |
| “New publishers can have up to 5 apps until KudosCRM approves their first one.” | You reached the starter app limit. | Get your first app approved, or ask KudosCRM to raise the limit. |
| “New publishers can have up to 5 test workspaces until KudosCRM approves their first app. Removed workspaces still count until your first app is approved.” | You reached the starter test workspace limit. | Reuse a workspace you already added, get your first app approved, or ask KudosCRM. |
| “Acme Telecom has 50 apps — the most a publisher can have. Contact KudosCRM if you need more.” | The platform app limit. | Contact KudosCRM. |
| “The host must be example.com or sit under it. Mark it test-only to use another host.” | A redirect, install, app or help URL is on another domain. | Use a host on your domain, or tick Test workspaces only for a redirect URL. |
| “KudosCRM can only send to a public address, and api.example.com isn't one it can reach. Check the host name.” | The webhook URL's host doesn't resolve on the public internet, or points to a private address such as localhost. | Use a public host that has a DNS record and is reachable from the internet, then save again. |
| “The logo must be square, at least 256 × 256. This one is …” | Wrong logo size. | Upload a square PNG, JPEG or WebP of 256 × 256 or more. |
| “Screenshots are 1600 × 1000, or larger at 16:10. This one is …” | Wrong screenshot size. | Export at exactly 16:10, at least 1600 × 1000. |
| “A listing has at most 6 screenshots. Delete one first.” | You already have six. | Delete one, then add. |
| “Upload a square logo on the Listing tab. Every app in the KudosCRM Marketplace shows one.” | Submit needs a logo. | Upload it on the Listing tab. |
| “Acme Telecom hasn't accepted the partner agreement yet. Accept it first.” | Submit needs the agreement. | Open Partner agreement and accept it. |
| “KudosCRM published version … of the partner agreement…” | A new version is in force. | Accept the new version, then submit. |
| “Nothing has changed since v1.0.” | The working copy equals the live version. | Make a change before you submit. |
| “Give reviewers a login for a test account in your app.” / “Add a link to a video of the install, start to finish.” | A submission field is empty. | Fill in the reviewer login or the install video URL. |
| “Acme Dialer can't be released until KudosCRM verifies Acme Telecom's domain, example.com…” | The domain isn't verified yet. | Ask KudosCRM to verify it, then release again. |
403 insufficient_scope | The install's grant doesn't include the scope this call needs. meta.required_scope names it. | Request the scope in a new version, or stop making that call. |
429 with Retry-After | The install used its hourly quota. | Wait the number of seconds in Retry-After. The review checks this. |
503 app_paused | The customer paused your app. | Wait. Events you send are kept and applied when they resume. |
403 app_suspended | KudosCRM suspended your app. | Contact KudosCRM. |
401, then invalid_grant on refresh | The install needs reconnecting (its grant was revoked). | Send the admin through /oauth/authorize again. |
| The Webhook signatures verified on a test delivery check fails | Your endpoint answered the wrong-signature ping with 2xx, or the real ping with an error. | Verify the signature first; answer 400 or 401 when it fails and 2xx when it passes. |
| A check reads Not run | There was nothing to measure in the last 30 days. The line under the check says why, for example “v1.0 has no webhook URL, so there is nothing to sign.” | Fill in what's missing (here, the webhook URL on the Events tab), install the app in a test workspace, use it for real, then Run again. |
Frequently asked questions
Does it cost anything to build or list an app?
No. Becoming a developer is free on any plan, the free plan included, and listing on KudosCRM is free. The Price label describes your own product's plans, not a KudosCRM fee.
How long does review take?
The console says “Review usually takes up to 5 business days.”
Who owns the customer data my app reads?
The workspace's data stays the customer's, in their KudosCRM workspace. Your app sees only what the admin approved on the consent screen. The consent screen tells the admin that your privacy policy and terms apply to the data your app receives, and your listing says your company is responsible for the app and its support. The admin can remove access at any time in Settings › Connected apps, which revokes your tokens.
Can I build a private app just for my own workspace?
Yes. Every app starts private: it installs only in your company's developer workspace. You can test it there, and in your test workspaces, without review. To release a version to your own workspace, choose Acme Telecom's workspace only in the release dialog; releasing needs an approved version. If only your workspace will ever use it, an API token and an outbound webhook are simpler than an app.
Can I change the app's key later?
No. The key is permanent. Everything else, including the name, can change in a later version.
Can more than one person on my team work on the app?
Yes. Every admin of your developer workspace with the Build, submit & release developer apps permission is a developer. See them under Team.
Does a test workspace need a paid plan?
No. A test workspace is any workspace where you are an owner or admin, other than your developer workspace.
Can I take my app off the Marketplace?
Once an app is public, only KudosCRM can take it off. Contact KudosCRM. Existing installs keep working when an app is taken off.
Why does my app not show on kudoscrm.com yet?
The website is rebuilt from the app registry. Your app appears there after the next website build. It shows in Settings › Marketplace in every workspace as soon as you release it.
Learn more
- Build an app (developer docs) — the full OAuth flow, install lifecycle and rate limits.
- KudosCRM integrations — the apps in the Marketplace.
Have an account issue this guide doesn't cover?
Start free today
Ready to give your team a CRM they'll actually use?
Start free. Bring your whole team. Cancel whenever (you won't).