--- title: Quick Start description: Integrate Duckity in less than 5 minutes. icon: Zap --- Getting started with Duckity is quite simple. Head over to [Duckity's Dashboard](https://app.duckity.com/) and log in using your favorite method. If it's your first time logging in, your account will be automatically created. ## Create an Application [step] Duckity is divided into one or more applications within your account. You create one application per project in which you want to integrate Duckity. To create a new application, press on the yellow **+ New Application** button at the top right corner of the screen. Once you've set the name of it, press on the **✓ Create Application** button. Congratulations! You now have your first application created. Additionally, in case your application is a web app, you can set up the CORS origins to fit your application's origins. For example, if you'll be protecting the login form of your app hosted at `https://example.com/login`, add `https://example.com` (scheme and host, no path) to your app's origins. If your application is not a web app, you can leave the CORS origins empty. ## Create a Protection Profile [step] Applications commonly have multiple features that need to be protected. For example, you may have a signup form and a login form with different protection needs. For each, you'll create one **protection profile** with settings tuned to each feature's specific needs. Each application needs at least one protection profile to work. To create your first one, press the **+ Create Protection Profile** button. Set the name to the name of the feature you'll be protecting, like "Sign-up Form" or "Add Friend". This is for you to recognize it later, it won't be displayed to your users. Once you're done filling it, press on **✓ Create Protection Profile**. Copy your protection profile's ID using the button at the top right corner, that's all you'll need to integrate it into your application. Don't worry about all the settings displayed for now, you'll learn to tune them later. ## Install a Client SDK [step] To integrate your protection profile into your application, you'll need to install a client SDK in your client and validate solution tokens from your server. This is very simple to do and will take you little to no time. Run the following line in your terminal to install the Duckity SDK. ```package-install @duckity/js ``` Then import it in your code: ```ts import * as duckity from "@duckity/js"; ``` If you're using the SDK from a static site, import it using a CDN like [esm.sh](https://esm.sh/) instead. ```html ``` Once you've imported the SDK, solve a challenge like follows: ```ts async function handleSubmit(e) { e.preventDefault(); const solution: string = await duckity.solve(PROTECTION_PROFILE_ID); // Send it to your backend. } ``` Send that solution token to your backend server. It's usually a good idea to send it in a `X-Duckity-Solution` header in your request, for example ```ts await fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json", "X-Duckity-Solution": solution }, body: JSON.stringify({ login: username, password: password, }), }); ``` You can read about advanced usage in the SDK's documentation page: }> Integrate Duckity into your application using the JavaScript SDK. Run the following line in your terminal to install the Duckity SDK. ```package-install @duckity/react ``` Then import the React hook in your code: ```ts import { useChallenge } from "@duckity/react"; ``` You can then use the hook in your client components: ```ts "use client"; import { useChallenge } from "@duckity/react"; function MyComponent() { const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID); } ``` ```ts import { useChallenge } from "@duckity/react"; function MyComponent() { const duckity = useChallenge(import.meta.env.VITE_DUCKITY_PROTECTION_PROFILE_ID); } ``` ```ts import { json } from "@remix-run/node"; // Or cloudflare/deno import { useLoaderData } from "@remix-run/react"; import { useChallenge } from "@duckity/react"; export async function loader() { return json({ ENV: { DUCKITY_PROTECTION_PROFILE_ID: process.env.DUCKITY_PROTECTION_PROFILE_ID, }, }); } function MyComponent() { const data = useLoaderData(); const duckity = useChallenge(data.ENV.DUCKITY_PROTECTION_PROFILE_ID); } ``` ```ts import { useChallenge } from "@duckity/react"; function MyComponent() { const duckity = useChallenge(process.env.GATSBY_DUCKITY_PROTECTION_PROFILE_ID); } ``` ```ts import { useChallenge } from "@duckity/react"; function MyComponent() { const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID); } ``` ```ts import { useChallenge } from "@duckity/react"; function MyComponent() { const duckity = useChallenge(import.meta.env.PUBLIC_DUCKITY_PROTECTION_PROFILE_ID); } ``` This is a client component, so use it as follows when rendering it: ```tsx ``` When the component is first rendered, it'll start fetching and solving a challenge. You can then wait for and use a solution token: ```ts async function handleSubmit(e) { e.preventDefault(); const solution = await duckity.wait(); // Send the solution token to your backend. } ``` Send that solution token to your backend server. It's usually a good idea to send it in a `X-Duckity-Solution` header in your request, for example ```ts await fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json", "X-Duckity-Solution": solution }, body: JSON.stringify({ login: username, password: password, }), }); ``` You can read about advanced usage in the SDK's documentation page: }> Integrate Duckity into your application using the React SDK. Install the SDK from PyPI using your favorite package manager: {/* prettier-ignore */} ```sh pip install duckity ``` ```sh uv add duckity ``` ```sh poetry add duckity ``` Solving a challenge only requires your protection profile ID. ```py import duckity solution: str = await duckity.solve(PROTECTION_PROFILE_ID) ``` The CPU-intensive part of solving the challenge is done in a `ProcessPoolExecutor()`. Neither the GIL nor the async event loop will be blocked. ```py import asyncio import duckity solution: str = asyncio.run(duckity.solve(PROTECTION_PROFILE_ID)) ``` The CPU-intensive part of solving the challenge is done in a `ProcessPoolExecutor()`. The GIL will not be blocked. Once you have a solution token, send it to your backend for validation. It's usually a good idea to send it in a `X-Duckity-Solution` request header, like follows: ```py import requests solution: str = asyncio.run(duckity.solve(PROTECTION_PROFILE_ID)) requests.post( "https://api.example.com/login", headers={ "Accept": "application/json", "X-Duckity-Solution": solution, }, json={ "login": username, "password": password } ) ``` You can read about advanced usage in the SDK's documentation page: }> Integrate Duckity into your application using the Python SDK. Run the following cargo command in your terminal to add the `duckity` crate to your project: ```sh cargo add duckity ``` The crate depends on `tokio`, you can use `async-compat` to make it work in `smol` contexts. To get and solve a challenge, use `duckity::solve()` like follows: ```rs let solution: str = duckity::solve(PROTECTION_PROFILE_ID).await?; ``` That's it! Once you have your solution token, you can send it over to your backend for validation. It's usually a good idea to send it in a `X-Duckity-Solution` request header, like follows: ```rs reqwest::Client::new() .post("https://api.example.com/login") .header("x-duckity-solution", solution) .json(&Login { login: username, password: password, }) .send() .await?; ``` You can read about advanced usage in the SDK's documentation page: }> Integrate Duckity into your application using the Rust SDK. In case your platform is a different one, we provide a detailed step-by-step guide on how to write your own client-side SDK implementation in any language, with code examples and pseudocode. It's written so that anyone can implement a working client-side implementation for any platform, so if you have a bit of time, you may be able to get it working in less than an hour. }> Integrate Duckity into your application in any programming language and platform. We constantly improve this guide with incoming feedback from developers like you. If you find anything that could be improved, let us know! Additionally, in case anything in the guide is not clear, open a support ticket in the dashboard and we'll try to help you out. Note that we're not experts in every language nor platform, so we likely won't be able to debug your code, rather help you understand what the guide says. ## Install a Server SDK [step] Once you have a solution token in your server, validating it is quite easy. Run the following line in your terminal to install the Duckity SDK. ```package-install @duckity/js ``` Then import it in your code: ```ts import * as duckity from "@duckity/js"; ``` To validate the solution token, use `duckity.validate()`. ```ts let isValid = await duckity.validate( solution, // The solution token submitted by the client. clientIp, // The IP address of the client that submitted the solution. applicationSecret, // Your application's secret. Get it from the dashboard. protectionProfileId, // The protection profile ID used to generate the challenge. ); ``` That's it! If the solution is not valid, reject the request with an error. Otherwise, proceed to process the rest of the request. Install the SDK from PyPI using your favorite package manager: {/* prettier-ignore */} ```sh pip install duckity ``` ```sh uv add duckity ``` ```sh poetry add duckity ``` Once you have done it, validate the solution token as follows: ```py import duckity solution: str # The solution token submitted by the client. client_ip: str # The IP address of the client that submitted the solution. application_secret: str # Your application's secret. Get it from the dashboard. protection_profile_id: str # The protection profile ID used to generate the challenge. is_valid: bool = await duckity.validate( solution, client_ip, application_secret, protection_profile_id ) ``` ```py import asyncio import duckity solution: str # The solution token submitted by the client. client_ip: str # The IP address of the client that submitted the solution. application_secret: str # Your application's secret. Get it from the dashboard. protection_profile_id: str # The protection profile ID used to generate the challenge. is_valid: bool = asyncio.run( duckity.validate(solution, client_ip, application_secret, protection_profile_id) ) ``` That's it! If the solution token is valid, you can proceed to process your request. If it's not, return an error to the client and do not further process the request. Run the following cargo command in your terminal to add the `duckity` crate to your project: ```sh cargo add duckity ``` Once you have it installed, you can validate solution tokens as follows: ```rs let is_valid: bool = duckity::validate( solution, // The solution token submitted by the client. client_ip, // The IP address of the client that submitted the solution. APPLICATION_SECRET, // Your application's secret. Get it from the dashboard. PROTECTION_PROFILE_ID // The protection profile ID used to generate the challenge. ) .await?; ``` That's it! If the solution token is valid, you can proceed to process your request. If it's not, return an error to the client and do not further process the request. In case you cannot or do not want to install an SDK, you can validate solution tokens by hand by making the HTTP request by hand instead. ```http POST /d1/challenges/{protection_profile_id}/validate HTTP/1.1 Host: api.duckity.com Accept: application/json Content-Type: application/json Authorization: Bearer {application_secret} { "solution": "", "ip": "" } ``` Validation responses are simple: ```http HTTP/1.1 200 OK Content-Type: application/json { "is_valid": true // or false } ``` ```http HTTP/1.1 401 Unauthorized Content-Type: application/json { "title": "Invalid Application Secret", "message": "The application secret you provided was not valid." } ``` ```http HTTP/1.1 404 Not Found Content-Type: application/json { "title": "Protection Profile Not Found", "message": "The protection profile ID you specified was not found." } ``` ```http HTTP/1.1 422 Unprocessable Entity Content-Type: application/json { "title": "Invalid Request Body", "message": "Are you sure the JSON body you sent in the request was valid?" } ``` ```http HTTP/1.1 429 Too Many Requests Content-Type: application/json { "title": "Too Many Requests", "message": "Wohoah, you're going too fast, buddy. Slow down a bit." } ``` ```http HTTP/1.1 500 Internal Server Error Content-Type: application/json { "title": "Internal Server Error", "message": "The server crashed. Please try again." } ``` That's it! If the solution token is valid, you can proceed to process your request. If it's not, return an error to the client and do not further process the request. Note that status codes are related to server actions, not to client actions. An invalid solution token submitted by the client will return `200` because the token was validated successfully (even if the result was that it was invalid), while a wrong application secret or an incorrect protection profile ID will return `4xx` status codes. ## Next Steps Once you have successfully integrated duckity into your application, you're done with the code part. The behavior of challenges issued is fully customizable from the Duckity dashboard. Almost every configuration can be easily understood by their dashboard description. However, to learn how to combine settings to produce a more powerful setup, check out the following guide. It goes configuration by configuration to teach you how to configure the parameters you need to suit your application's needs. } > Learn how to tune your protection profiles to better protect your application while enhancing your users' experiences.