# Dub > ## Documentation Index --- # Source: https://dub.co/docs/api-reference/endpoint/approve-a-bounty-submission.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Approve a bounty submission > Approve a bounty submission. Optionally specify a custom reward amount. ## OpenAPI ````yaml post /bounties/{bountyId}/submissions/{submissionId}/approve openapi: 3.0.3 info: title: Dub API description: >- Dub is the modern link attribution platform for short links, conversion tracking, and affiliate programs. version: 0.0.1 contact: name: Dub Support email: support@dub.co url: https://dub.co/api license: name: AGPL-3.0 license url: https://github.com/dubinc/dub/blob/main/LICENSE.md servers: - url: https://api.dub.co description: Production API security: [] paths: /bounties/{bountyId}/submissions/{submissionId}/approve: post: tags: - Bounties summary: Approve a bounty submission description: Approve a bounty submission. Optionally specify a custom reward amount. operationId: approveBountySubmission parameters: - in: path name: bountyId schema: type: string required: true - in: path name: submissionId schema: type: string required: true requestBody: content: application/json: schema: type: object properties: rewardAmount: nullable: true type: number responses: '200': description: The approved bounty submission. content: application/json: schema: type: object properties: id: type: string bountyId: type: string partnerId: type: string description: nullable: true type: string urls: nullable: true type: array items: type: string files: nullable: true type: array items: type: object properties: url: type: string fileName: type: string size: type: number required: - url - fileName - size additionalProperties: false status: type: string enum: - draft - submitted - approved - rejected performanceCount: nullable: true type: number createdAt: type: string completedAt: nullable: true type: string reviewedAt: nullable: true type: string rejectionReason: nullable: true type: string rejectionNote: nullable: true type: string required: - id - bountyId - partnerId - description - urls - files - status - performanceCount - createdAt - completedAt - reviewedAt - rejectionReason - rejectionNote additionalProperties: false '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': $ref: '#/components/responses/403' '404': $ref: '#/components/responses/404' '409': $ref: '#/components/responses/409' '410': $ref: '#/components/responses/410' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' '500': $ref: '#/components/responses/500' security: - token: [] components: responses: '400': description: >- The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). content: application/json: schema: x-speakeasy-name-override: BadRequest type: object properties: error: type: object properties: code: type: string enum: - bad_request description: A short code indicating the error code returned. example: bad_request message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#bad-request required: - code - message required: - error '401': description: >- Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. content: application/json: schema: x-speakeasy-name-override: Unauthorized type: object properties: error: type: object properties: code: type: string enum: - unauthorized description: A short code indicating the error code returned. example: unauthorized message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#unauthorized required: - code - message required: - error '403': description: >- The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. content: application/json: schema: x-speakeasy-name-override: Forbidden type: object properties: error: type: object properties: code: type: string enum: - forbidden description: A short code indicating the error code returned. example: forbidden message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#forbidden required: - code - message required: - error '404': description: The server cannot find the requested resource. content: application/json: schema: x-speakeasy-name-override: NotFound type: object properties: error: type: object properties: code: type: string enum: - not_found description: A short code indicating the error code returned. example: not_found message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#not-found required: - code - message required: - error '409': description: >- This response is sent when a request conflicts with the current state of the server. content: application/json: schema: x-speakeasy-name-override: Conflict type: object properties: error: type: object properties: code: type: string enum: - conflict description: A short code indicating the error code returned. example: conflict message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#conflict required: - code - message required: - error '410': description: >- This response is sent when the requested content has been permanently deleted from server, with no forwarding address. content: application/json: schema: x-speakeasy-name-override: InviteExpired type: object properties: error: type: object properties: code: type: string enum: - invite_expired description: A short code indicating the error code returned. example: invite_expired message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#invite-expired required: - code - message required: - error '422': description: >- The request was well-formed but was unable to be followed due to semantic errors. content: application/json: schema: x-speakeasy-name-override: UnprocessableEntity type: object properties: error: type: object properties: code: type: string enum: - unprocessable_entity description: A short code indicating the error code returned. example: unprocessable_entity message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#unprocessable-entity required: - code - message required: - error '429': description: >- The user has sent too many requests in a given amount of time ("rate limiting") content: application/json: schema: x-speakeasy-name-override: RateLimitExceeded type: object properties: error: type: object properties: code: type: string enum: - rate_limit_exceeded description: A short code indicating the error code returned. example: rate_limit_exceeded message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#rate-limit_exceeded required: - code - message required: - error '500': description: The server has encountered a situation it does not know how to handle. content: application/json: schema: x-speakeasy-name-override: InternalServerError type: object properties: error: type: object properties: code: type: string enum: - internal_server_error description: A short code indicating the error code returned. example: internal_server_error message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#internal-server_error required: - code - message required: - error securitySchemes: token: type: http description: Default authentication mechanism scheme: bearer x-speakeasy-example: DUB_API_KEY ```` --- # Source: https://dub.co/docs/conversions/leads/appwrite.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Appwrite > Learn how to track lead conversion events with Appwrite and Dub Conversion tracking requires a [Business plan](https://dub.co/pricing) subscription or higher. When it comes to [conversion tracking](/conversions/quickstart), a `lead` event happens when a user performs an action that indicates interest in your product or service. This could be anything from: * Signing up for an account * Booking a demo meeting * Joining a mailing list A diagram showing how lead events are tracked in the conversion funnel In this guide, we will be focusing on tracking new user sign-ups for a SaaS application that uses Appwrite for user authentication. ## Prerequisites First, you'll need to enable conversion tracking for your Dub links to be able to start tracking conversions: If you're using [Dub Partners](/partners/quickstart), you can skip this step since partner links will have conversion tracking enabled by default. To enable conversion tracking for all future links in a workspace, you can do the following: To enable conversion tracking for all future links in a workspace, you can do the following: 1. Navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics). 2. Toggle the **Workspace-level Conversion Tracking** switch to enable conversion tracking for the workspace. Enabling conversion tracking for a workspace This option will enable conversion tracking in the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for all future links. If you don't want to enable conversion tracking for all your links in a workspace, you can also opt to enable it on a link-level. To enable conversion tracking for a specific link, open the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for a link and toggle the **Conversion Tracking** switch. Enabling conversion tracking for a link You can also use the `C` keyboard shortcut when inside the link builder to quickly enable conversion tracking for a given link. Alternatively, you can also enable conversion tracking programmatically via the [Dub API](/api-reference/introduction). All you need to do is pass `trackConversion: true` when creating or updating a link: ```javascript Node.js theme={null} const link = await dub.links.create({ url: "https://dub.co", trackConversion: true, }); ``` ```python Python theme={null} link = d.links.create(url="https://dub.co", track_conversion=True) ``` ```go Go theme={null} link, err := d.Links.Create(ctx, &dub.CreateLinkRequest{ URL: "https://dub.co", TrackConversion: true, }) ``` ```ruby Ruby theme={null} s.links.create_many( ::OpenApiSDK::Operations::CreateLinkRequest.new( url: "https://dub.co", track_conversion: true, ) ) ``` Then, you'd want to install the `@dub/analytics` script to your website to track conversion events. You can install the `@dub/analytics` script in several different ways: } href="/sdks/client-side/installation-guides/framer" horizontal /> You can **verify the installation** with the following tests: 1. Open the browser console and type in `_dubAnalytics` – if the script is installed correctly, you should see the `_dubAnalytics` object in the console. 2. Add the `?dub_id=test` query parameter to your website URL and make sure that the `dub_id` cookie is being set in your browser. If both of these checks pass, the script is installed correctly. Otherwise, please make sure: * The analytics script was added to the `` section of the page * If you're using a content delivery network (CDN), make sure to purge any cached content ## Configure Appwrite Next, configure Appwrite to track lead conversion events during the sign up process. Head to [Appwrite Cloud](https://apwr.dev/appwrite-dub) and create a new project. New project on Appwrite Cloud Create a new API key with the `sessions.write` scope enabled and save the API key for later use. You can also copy your project ID and endpoint from the project's Settings page. API key in your project on Appwrite Cloud Then, in your Next.js app, install the Appwrite Node.js SDK. ```bash theme={null} npm i node-appwrite ``` Add the following environment variables to your app. ```bash theme={null} NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1 NEXT_PUBLIC_APPWRITE_PROJECT= NEXT_APPWRITE_KEY= NEXT_DUB_API_KEY= ``` Add the `DubAnalytics` component from the `@dub/analytics` package to your app’s root layout. ```tsx src/app/layout.tsx theme={null} import type { Metadata } from 'next'; import { Analytics as DubAnalytics } from '@dub/analytics/react'; export const metadata: Metadata = { title: 'Appwrite Dub Leads Example', description: 'Appwrite Dub Leads Tracking example app with Next.js' }; export default function RootLayout({ children }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ``` Create the Appwrite Session and Admin client (necessary for SSR apps, as explained in the [Appwrite docs](https://appwrite.io/docs/products/auth/server-side-rendering)). Additionally, create a function to verify user login. ```ts src/lib/server/appwrite.ts theme={null} 'use server'; import { Client, Account } from 'node-appwrite'; import { cookies } from 'next/headers'; export async function createSessionClient() { const client = new Client() .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT as string) .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT as string); const session = (await cookies()).get('my-custom-session'); if (!session || !session.value) { throw new Error('No session'); } client.setSession(session.value); return { get account() { return new Account(client); } }; } export async function createAdminClient() { const client = new Client() .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT as string) .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT as string) .setKey(process.env.NEXT_APPWRITE_KEY as string); return { get account() { return new Account(client); } }; } ``` Create the Dub client and send leads to Dub using the `dub.track.lead()` function. ```ts src/lib/server/dub.ts theme={null} import type { Models } from 'node-appwrite'; import { Dub } from 'dub'; const dub = new Dub({ token: process.env.NEXT_DUB_API_KEY }); export function addDubLead(user: Models.User, dub_id: string) { dub.track.lead({ clickId: dub_id, eventName: 'Sign Up', customerExternalId: user.$id, customerName: user.name, customerEmail: user.email }); } ``` In the `/auth` page, use the Appwrite Admin client to allow users to sign up. Post sign up, check if the `dub_id` cookie is present, send a lead event to Dub if found, and delete the `dub_id` cookie. ```tsx src/app/auth/page.tsx theme={null} import { ID } from 'node-appwrite'; import { createAdminClient, getLoggedInUser } from '@/lib/server/appwrite'; import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; import { addDubLead } from '@/lib/server/dub'; async function signUpWithEmail(formData: any) { 'use server'; // Get sign up info from form const email = formData.get('email'); const password = formData.get('password'); const name = formData.get('name'); // Create account and session using Appwrite const { account } = await createAdminClient(); const user = await account.create(ID.unique(), email, password, name); const session = await account.createEmailPasswordSession(email, password); (await cookies()).set('my-custom-session', session.secret, { path: '/', httpOnly: true, sameSite: 'strict', secure: true }); // Check if Dub ID is present in cookies and track lead if found const dub_id = (await cookies()).get('dub_id')?.value; if (dub_id) { addDubLead(user, dub_id); (await cookies()).delete('dub_id'); } // Redirect to success page redirect('/auth/success'); } export default async function SignUpPage() { // Verify active user session and redirect to success page if found const user = await getLoggedInUser(); if (user) redirect('/auth/success'); return ( <>
); } ```
Here's the full list of attributes you can pass when sending a lead event: | Property | Required | Description | | :------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `clickId` | **Yes** | The unique ID of the click that the lead conversion event is attributed to. You can read this value from `dub_id` cookie. If an empty string is provided (i.e. if you're using [tracking a deferred lead event](/conversions/leads/deferred)), Dub will try to find an existing customer with the provided `customerExternalId` and use the `clickId` from the customer if found. | | `eventName` | **Yes** | The name of the lead event to track. Can also be used as a unique identifier to associate a given lead event for a customer for a subsequent sale event (via the `leadEventName` prop in `/track/sale`). | | `customerExternalId` | **Yes** | The unique ID of the customer in your system. Will be used to identify and attribute all future events to this customer. | | `customerName` | No | The name of the customer. If not passed, a random name will be generated (e.g. "Big Red Caribou"). | | `customerEmail` | No | The email address of the customer. | | `customerAvatar` | No | The avatar URL of the customer. | | `mode` | No | The mode to use for tracking the lead event. `async` will not block the request; `wait` will block the request until the lead event is fully recorded in Dub; `deferred` will defer the lead event creation to a subsequent request. | | `metadata` | No | Additional metadata to be stored with the lead event. Max 10,000 characters. | ## Example App To learn more about how to track leads with Appwrite, check out the following example app: See how to track new user sign-ups with Appwrite and the Dub SDK. ## View your conversions Once you've completed the setup, all your tracked conversions will show up in [Dub Analytics](https://dub.co/analytics). We provide 3 different views to help you understand your conversions: * **Time-series**: A [time-series view](https://app.dub.co/dub/analytics?view=timeseries) of the number clicks, leads and sales. Time-series line chart * **Funnel chart**: A [funnel chart view](http://app.dub.co/analytics?view=funnel) visualizing the conversion & dropoff rates across the different steps in the conversion funnel (clicks → leads → sales). Funnel chart view showing the conversion & dropoff rates from clicks → leads → sales * **Real-time events stream**: A [real-time events stream](https://app.dub.co/events) of every single conversion event that occurs across all your links in your workspace. The Events Stream dashboard on Dub --- # Source: https://dub.co/docs/concepts/deep-links/attribution.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Deep link attribution > Learn how to use deep link attribution to track conversions events with Dub. Deep link attribution requires a [Business plan](https://dub.co/pricing) subscription or higher. Dub's powerful [attribution platform](https://dub.co/analytics) lets you understand how well your deep links are translating to actual users and revenue dollars inside your app. Conversion analytics This feature is currently only available for iOS (Swift). React Native and Android support are coming soon. If you'd like early access, please [contact us](https://dub.co/contact/support). ## Prerequisites First, you'll need to enable conversion tracking for your Dub links to be able to start tracking conversions: If you're using [Dub Partners](/partners/quickstart), you can skip this step since partner links will have conversion tracking enabled by default. To enable conversion tracking for all future links in a workspace, you can do the following: To enable conversion tracking for all future links in a workspace, you can do the following: 1. Navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics). 2. Toggle the **Workspace-level Conversion Tracking** switch to enable conversion tracking for the workspace. Enabling conversion tracking for a workspace This option will enable conversion tracking in the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for all future links. If you don't want to enable conversion tracking for all your links in a workspace, you can also opt to enable it on a link-level. To enable conversion tracking for a specific link, open the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for a link and toggle the **Conversion Tracking** switch. Enabling conversion tracking for a link You can also use the `C` keyboard shortcut when inside the link builder to quickly enable conversion tracking for a given link. Alternatively, you can also enable conversion tracking programmatically via the [Dub API](/api-reference/introduction). All you need to do is pass `trackConversion: true` when creating or updating a link: ```javascript Node.js theme={null} const link = await dub.links.create({ url: "https://dub.co", trackConversion: true, }); ``` ```python Python theme={null} link = d.links.create(url="https://dub.co", track_conversion=True) ``` ```go Go theme={null} link, err := d.Links.Create(ctx, &dub.CreateLinkRequest{ URL: "https://dub.co", TrackConversion: true, }) ``` ```ruby Ruby theme={null} s.links.create_many( ::OpenApiSDK::Operations::CreateLinkRequest.new( url: "https://dub.co", track_conversion: true, ) ) ``` Then, you'll need generate a [publishable key](/api-reference/publishable-keys) from your Dub workspace to track conversions on the client-side. To do that, navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and generate a new publishable key under the **Publishable Key** section. Enabling conversion tracking for a workspace Once these are set up, we can start tracking conversion events for your deep links. ## Step 1: Install the client-side Mobile SDK Install the [Dub React Native SDK](/sdks/client-side-mobile/installation-guides/react-native) and initialize it with your publishable key and short link domain. ```sh theme={null} # With npm npm install @dub/react-native # With yarn yarn add @dub/react-native # With pnpm pnpm add @dub/react-native ``` You must call `init` on your `dub` instance with your publishable key and domain prior to being able to use the `dub` instance. We provide two ways to initialize the SDK: **Option 1**: Use the `DubProvider` to wrap your app ```typescript theme={null} import { DubProvider } from "@dub/react-native"; export default function App() { return ( // Your app content... ); } ``` **Option 2**: Manually initialize the Dub SDK ```typescript theme={null} import dub from "@dub/react-native"; export default function App() { useEffect(() => { dub.init({ publishableKey: "", domain: "", }); }, []); // Return your app... } ``` Install the [Dub iOS SDK](/sdks/client-side-mobile/installation-guides/swift) and initialize it with your publishable key and short link domain. Before installing, ensure your environment meets these minimum requirements: **Build Tools:** * Xcode 16+ * Swift 4.0+ **Platforms:** * iOS 16.0+ * macOS 10.13 (Ventura)+ The Dub iOS SDK can be installed using the [Swift Package Manager](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/). In Xcode, select **File** > **Add Package Dependencies** and add `https://github.com/dubinc/dub-ios` as the repository URL. Select the latest version of the SDK from the [release page](https://github.com/dubinc/dub-ios/releases). You must call `Dub.setup` with your publishable key and domain prior to being able to use the `dub` instance. ```swift iOS (SwiftUI) theme={null} import SwiftUI import Dub @main struct DubApp: App { // Step 1: Obtain your Dub domain and publishable key private let dubPublishableKey = "" private let dubDomain = "" init() { // Step 2: Initialize the Dub SDK by calling `setup` Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) } var body: some Scene { WindowGroup { ContentView() // Step 3: Expose the `dub` instance as a SwiftUI environment value .environment(\.dub, Dub.shared) } } } ``` ```swift iOS (UIKit) theme={null} import UIKit import Dub @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? // Step 1: Obtain your Dub domain and publishable key private let dubPublishableKey = "" private let dubDomain = "" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Step 2: Initialize the Dub SDK by calling `setup` Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) return true } } ``` ## Step 2: Track deep link open events Once the SDK has been initialized, you can start tracking deep link and deferred deep link events. Call `trackOpen` on the `dub` instance to track deep link and deferred deep link open events. The `trackOpen` function should be called once without a `deepLink` parameter on first launch, and then again with the `deepLink` parameter whenever the app is opened from a deep link. ```typescript React Native expandable theme={null} import { useState, useEffect, useRef } from "react"; import { Linking } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; import dub from "@dub/react-native"; export default function App() { useEffect(() => { dub.init({ publishableKey: "", domain: "", }); // Check if this is first launch const isFirstLaunch = await AsyncStorage.getItem("is_first_launch"); if (isFirstLaunch === null) { await handleFirstLaunch(); await AsyncStorage.setItem("is_first_launch", "false"); } else { // Handle initial deep link url (Android only) const url = await Linking.getInitialURL(); if (url) { await handleDeepLink(url); } } const linkingListener = Linking.addEventListener("url", (event) => { handleDeepLink(event.url); }); return () => { linkingListener.remove(); }; }, []); const handleFirstLaunch = async ( deepLinkUrl?: string | null | undefined ): Promise => { try { const response = await dub.trackOpen(deepLinkUrl); const destinationURL = response.link?.url; // Navigate to the destination URL } catch (error) { // Handle error } }; // Return your app... } ``` ```swift iOS (SwiftUI) expandable theme={null} // ContentView.swift import SwiftUI import Dub struct ContentView: View { @Environment(\.dub) var dub: Dub @AppStorage("is_first_launch") private var isFirstLaunch = true var body: some View { NavigationStack { VStack { // Your app content } .onOpenURL { url in trackOpen(deepLink: url) } .onAppear { if isFirstLaunch { trackOpen() isFirstLaunch = false } } } } private func trackOpen(deepLink: URL? = nil) { Task { do { let response = try await dub.trackOpen(deepLink: deepLink) // Obtain the destination URL from the response guard let url = response.link?.url else { return } // Navigate to the destination URL } catch let error as DubError { print(error.localizedDescription) } } } } ``` ```swift iOS (UIKit) expandable theme={null} import UIKit import Dub @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? private let dubPublishableKey = "" private let dubDomain = "" private var isFirstLaunch: Bool { get { UserDefaults.standard.object(forKey: "is_first_launch") as? Bool ?? true } set { UserDefaults.standard.set(newValue, forKey: "is_first_launch") } } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) // Track first launch if isFirstLaunch { trackOpen() isFirstLaunch = false } // Override point for customization after application launch. return true } func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { handleDeepLink(url: url) return true } func handleDeepLink(url: URL) { trackOpen(deepLink: url) } private func trackOpen(deepLink: URL? = nil) { // Call the tracking endpoint with the full deep link URL Task { do { let response = try await Dub.shared.trackOpen(deepLink: deepLink) print(response) // Navigate to final link via link.url guard let destinationUrl = response.link?.url else { return } // Navigate to the destination URL } catch let error as DubError { print(error.localizedDescription) } } } } ``` If the deep link was successfully resolved and correlated to the original click, the `response` object will contain the destination URL, which you can use to navigate the user to the appropriate screen. It will also contain the `clickId`, which the `dub` instance will persist internally. ## Step 3: Track conversion events You may track conversion events directly in your app with the `trackLead` and `trackSale` methods. ```typescript React Native expandable theme={null} import dub from "@dub/react-native"; function trackLead(user: User) { try { await dub.trackLead({ eventName: "User Sign Up", customerExternalId: user.id, customerName: user.name, customerEmail: user.email, }); } catch (error) { // Handle sale tracking error } } function trackSale(user: User, product: Product) { try { await dub.trackSale({ customerExternalId: user.id, amount: product.price.amount, currency: "usd", eventName: "Purchase", }); } catch (error) { // Handle sale tracking error } } ``` ```swift iOS (SwiftUI) expandable theme={null} // ContentView.swift import SwiftUI import Dub struct ContentView: View { @Environment(\.dub) var dub: Dub var body: some View { // ... your app content ... } private func trackLead(customerExternalId: String, name: String, email: String) { Task { do { let response = try await dub.trackLead( eventName: "Sign Up", customerExternalId: customerExternalId, customerName: name, customerEmail: email ) print(response) } catch let error as DubError { print(error.localizedDescription) } } } private func trackSale( customerExternalId: String, amount: Int, currency: String = "usd", eventName: String? = "Purchase", customerName: String? = nil, customerEmail: String? = nil, customerAvatar: String? = nil ) { Task { do { let response = try await dub.trackSale( customerExternalId: customerExternalId, amount: amount, currency: currency, eventName: eventName, customerName: customerName, customerEmail: customerEmail, customerAvatar: customerAvatar ) print(response) } catch let error as DubError { print(error.localizedDescription) } } } } ``` ```swift iOS (UIKit) expandable theme={null} // ViewController.swift import UIKit import Dub class ViewController: UIViewController { // View controller lifecycle private func trackLead(customerExternalId: String, name: String, email: String) { Task { do { let response = try await dub.trackLead(customerExternalId: customerExternalId, name: name, email: email) } catch let error as DubError { print(error.localizedDescription) } } } private func trackSale(customerExternalId: String, amount: Int, currency: String = "usd", eventName: String? = "Purchase", customerName: String? = nil, customerEmail: String? = nil, customerAvatar: String? = nil) { Task { do { let response = try await dub.trackSale(customerExternalId: customerExternalId, amount: amount, currency: currency, eventName: eventName, customerName: customerName, customerEmail: customerEmail, customerAvatar: customerAvatar) } catch let error as DubError { print(error.localizedDescription) } } } } ``` Alternatively, you can [track conversion events server-side](/conversions/quickstart#step-3%3A-install-the-dub-server-side-sdk-%2B-track-conversion-events) for [lead events](/conversions/leads/introduction) and [sale events](/conversions/sales/introduction) by sending the `clickId` resolved from the deep link to your backend and then calling off to either: * [`POST /track/lead`](https://dub.co/docs/api-reference/endpoint/track-lead) * [`POST /track/sale`](https://dub.co/docs/api-reference/endpoint/track-sale) ## Step 4: View your conversions Once you've enabled conversion tracking for your links, all your tracked conversions will show up on your [Analytics dashboard](https://app.dub.co/analytics). We provide 3 different views to help you understand your conversions: * **Time-series**: A [time-series view](https://app.dub.co/dub/analytics?view=timeseries) of the number clicks, leads and sales. Time-series line chart * **Funnel chart**: A [funnel chart view](http://app.dub.co/analytics?view=funnel) visualizing the conversion & dropoff rates across the different steps in the conversion funnel (clicks → leads → sales). Funnel chart view showing the conversion & dropoff rates from clicks → leads → sales * **Real-time events stream**: A [real-time events stream](https://app.dub.co/events) of every single conversion event that occurs across all your links in your workspace. The Events Stream dashboard on Dub --- # Source: https://dub.co/docs/conversions/leads/auth0.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Auth0 > Learn how to track lead conversion events with Auth0 and Dub Conversion tracking requires a [Business plan](https://dub.co/pricing) subscription or higher. When it comes to [conversion tracking](/conversions/quickstart), a `lead` event happens when a user performs an action that indicates interest in your product or service. This could be anything from: * Signing up for an account * Booking a demo meeting * Joining a mailing list A diagram showing how lead events are tracked in the conversion funnel In this guide, we will be focusing on tracking new user sign-ups for a SaaS application that uses Auth0 for user authentication. ## Prerequisites First, you'll need to enable conversion tracking for your Dub links to be able to start tracking conversions: If you're using [Dub Partners](/partners/quickstart), you can skip this step since partner links will have conversion tracking enabled by default. To enable conversion tracking for all future links in a workspace, you can do the following: To enable conversion tracking for all future links in a workspace, you can do the following: 1. Navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics). 2. Toggle the **Workspace-level Conversion Tracking** switch to enable conversion tracking for the workspace. Enabling conversion tracking for a workspace This option will enable conversion tracking in the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for all future links. If you don't want to enable conversion tracking for all your links in a workspace, you can also opt to enable it on a link-level. To enable conversion tracking for a specific link, open the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for a link and toggle the **Conversion Tracking** switch. Enabling conversion tracking for a link You can also use the `C` keyboard shortcut when inside the link builder to quickly enable conversion tracking for a given link. Alternatively, you can also enable conversion tracking programmatically via the [Dub API](/api-reference/introduction). All you need to do is pass `trackConversion: true` when creating or updating a link: ```javascript Node.js theme={null} const link = await dub.links.create({ url: "https://dub.co", trackConversion: true, }); ``` ```python Python theme={null} link = d.links.create(url="https://dub.co", track_conversion=True) ``` ```go Go theme={null} link, err := d.Links.Create(ctx, &dub.CreateLinkRequest{ URL: "https://dub.co", TrackConversion: true, }) ``` ```ruby Ruby theme={null} s.links.create_many( ::OpenApiSDK::Operations::CreateLinkRequest.new( url: "https://dub.co", track_conversion: true, ) ) ``` Then, you'd want to install the `@dub/analytics` script to your website to track conversion events. You can install the `@dub/analytics` script in several different ways: } href="/sdks/client-side/installation-guides/framer" horizontal /> You can **verify the installation** with the following tests: 1. Open the browser console and type in `_dubAnalytics` – if the script is installed correctly, you should see the `_dubAnalytics` object in the console. 2. Add the `?dub_id=test` query parameter to your website URL and make sure that the `dub_id` cookie is being set in your browser. If both of these checks pass, the script is installed correctly. Otherwise, please make sure: * The analytics script was added to the `` section of the page * If you're using a content delivery network (CDN), make sure to purge any cached content ## Configure Auth0 Next, configure Auth0 to track lead conversion events. Here's how it works in a nutshell: 1. In the sign in `afterCallback` function, check if the user is a new sign up. 2. If the user is a new sign up, check if the `dub_id` cookie is present. 3. If the `dub_id` cookie is present, send a lead event to Dub using `dub.track.lead` 4. Delete the `dub_id` cookie. ```typescript app/api/auth/[auth0]/route.js theme={null} import { handleAuth, handleCallback, type Session } from "@auth0/nextjs-auth0"; import { cookies } from "next/headers"; import { dub } from "@/lib/dub"; const afterCallback = async (req: Request, session: Session) => { const userExists = await getUser(session.user.email); if (!userExists) { createUser(session.user); // check if dub_id cookie is present const clickId = cookies().get("dub_id")?.value; if (clickId) { // send lead event to Dub await dub.track.lead({ clickId, eventName: "Sign Up", customerExternalId: session.user.id, customerName: session.user.name, customerEmail: session.user.email, customerAvatar: session.user.image, }); // delete the dub_id cookie cookies().set("dub_id", "", { expires: new Date(0), }); } return session; } }; export default handleAuth({ callback: handleCallback({ afterCallback }), }); ``` Here's the full list of attributes you can pass when sending a lead event: | Property | Required | Description | | :------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `clickId` | **Yes** | The unique ID of the click that the lead conversion event is attributed to. You can read this value from `dub_id` cookie. If an empty string is provided (i.e. if you're using [tracking a deferred lead event](/conversions/leads/deferred)), Dub will try to find an existing customer with the provided `customerExternalId` and use the `clickId` from the customer if found. | | `eventName` | **Yes** | The name of the lead event to track. Can also be used as a unique identifier to associate a given lead event for a customer for a subsequent sale event (via the `leadEventName` prop in `/track/sale`). | | `customerExternalId` | **Yes** | The unique ID of the customer in your system. Will be used to identify and attribute all future events to this customer. | | `customerName` | No | The name of the customer. If not passed, a random name will be generated (e.g. "Big Red Caribou"). | | `customerEmail` | No | The email address of the customer. | | `customerAvatar` | No | The avatar URL of the customer. | | `mode` | No | The mode to use for tracking the lead event. `async` will not block the request; `wait` will block the request until the lead event is fully recorded in Dub; `deferred` will defer the lead event creation to a subsequent request. | | `metadata` | No | Additional metadata to be stored with the lead event. Max 10,000 characters. | ## View your conversions Once you've completed the setup, all your tracked conversions will show up in [Dub Analytics](https://dub.co/analytics). We provide 3 different views to help you understand your conversions: * **Time-series**: A [time-series view](https://app.dub.co/dub/analytics?view=timeseries) of the number clicks, leads and sales. Time-series line chart * **Funnel chart**: A [funnel chart view](http://app.dub.co/analytics?view=funnel) visualizing the conversion & dropoff rates across the different steps in the conversion funnel (clicks → leads → sales). Funnel chart view showing the conversion & dropoff rates from clicks → leads → sales * **Real-time events stream**: A [real-time events stream](https://app.dub.co/events) of every single conversion event that occurs across all your links in your workspace. The Events Stream dashboard on Dub --- # Source: https://dub.co/docs/api-reference/endpoint/ban-a-partner.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Ban a partner > Ban a partner from your program. This will disable all links and mark all commissions as canceled. Partners endpoints require an [Advanced plan](https://dub.co/pricing) subscription or higher. ## OpenAPI ````yaml post /partners/ban openapi: 3.0.3 info: title: Dub API description: >- Dub is the modern link attribution platform for short links, conversion tracking, and affiliate programs. version: 0.0.1 contact: name: Dub Support email: support@dub.co url: https://dub.co/api license: name: AGPL-3.0 license url: https://github.com/dubinc/dub/blob/main/LICENSE.md servers: - url: https://api.dub.co description: Production API security: [] paths: /partners/ban: post: tags: - Partners summary: Ban a partner description: >- Ban a partner from your program. This will disable all links and mark all commissions as canceled. operationId: banPartner requestBody: content: application/json: schema: type: object properties: partnerId: description: >- The ID of the partner to create a link for. Will take precedence over `tenantId` if provided. nullable: true type: string tenantId: description: >- The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown. nullable: true type: string reason: type: string enum: - tos_violation - inappropriate_content - fake_traffic - fraud - spam - brand_abuse required: - reason responses: '200': description: The banned partner content: application/json: schema: type: object properties: partnerId: type: string description: The ID of the banned partner. required: - partnerId additionalProperties: false '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': $ref: '#/components/responses/403' '404': $ref: '#/components/responses/404' '409': $ref: '#/components/responses/409' '410': $ref: '#/components/responses/410' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' '500': $ref: '#/components/responses/500' security: - token: [] components: responses: '400': description: >- The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). content: application/json: schema: x-speakeasy-name-override: BadRequest type: object properties: error: type: object properties: code: type: string enum: - bad_request description: A short code indicating the error code returned. example: bad_request message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#bad-request required: - code - message required: - error '401': description: >- Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. content: application/json: schema: x-speakeasy-name-override: Unauthorized type: object properties: error: type: object properties: code: type: string enum: - unauthorized description: A short code indicating the error code returned. example: unauthorized message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#unauthorized required: - code - message required: - error '403': description: >- The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. content: application/json: schema: x-speakeasy-name-override: Forbidden type: object properties: error: type: object properties: code: type: string enum: - forbidden description: A short code indicating the error code returned. example: forbidden message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#forbidden required: - code - message required: - error '404': description: The server cannot find the requested resource. content: application/json: schema: x-speakeasy-name-override: NotFound type: object properties: error: type: object properties: code: type: string enum: - not_found description: A short code indicating the error code returned. example: not_found message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#not-found required: - code - message required: - error '409': description: >- This response is sent when a request conflicts with the current state of the server. content: application/json: schema: x-speakeasy-name-override: Conflict type: object properties: error: type: object properties: code: type: string enum: - conflict description: A short code indicating the error code returned. example: conflict message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#conflict required: - code - message required: - error '410': description: >- This response is sent when the requested content has been permanently deleted from server, with no forwarding address. content: application/json: schema: x-speakeasy-name-override: InviteExpired type: object properties: error: type: object properties: code: type: string enum: - invite_expired description: A short code indicating the error code returned. example: invite_expired message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#invite-expired required: - code - message required: - error '422': description: >- The request was well-formed but was unable to be followed due to semantic errors. content: application/json: schema: x-speakeasy-name-override: UnprocessableEntity type: object properties: error: type: object properties: code: type: string enum: - unprocessable_entity description: A short code indicating the error code returned. example: unprocessable_entity message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#unprocessable-entity required: - code - message required: - error '429': description: >- The user has sent too many requests in a given amount of time ("rate limiting") content: application/json: schema: x-speakeasy-name-override: RateLimitExceeded type: object properties: error: type: object properties: code: type: string enum: - rate_limit_exceeded description: A short code indicating the error code returned. example: rate_limit_exceeded message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#rate-limit_exceeded required: - code - message required: - error '500': description: The server has encountered a situation it does not know how to handle. content: application/json: schema: x-speakeasy-name-override: InternalServerError type: object properties: error: type: object properties: code: type: string enum: - internal_server_error description: A short code indicating the error code returned. example: internal_server_error message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#internal-server_error required: - code - message required: - error securitySchemes: token: type: http description: Default authentication mechanism scheme: bearer x-speakeasy-example: DUB_API_KEY ```` --- # Source: https://dub.co/docs/conversions/leads/better-auth.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Better Auth > Learn how to track lead conversion events with Better Auth and Dub Conversion tracking requires a [Business plan](https://dub.co/pricing) subscription or higher. When it comes to [conversion tracking](/conversions/quickstart), a `lead` event happens when a user performs an action that indicates interest in your product or service. This could be anything from: * Signing up for an account * Booking a demo meeting * Joining a mailing list A diagram showing how lead events are tracked in the conversion funnel In this guide, we will be focusing on tracking new user sign-ups for a SaaS application that uses Better Auth for user authentication. ## Prerequisites First, you'll need to enable conversion tracking for your Dub links to be able to start tracking conversions: If you're using [Dub Partners](/partners/quickstart), you can skip this step since partner links will have conversion tracking enabled by default. To enable conversion tracking for all future links in a workspace, you can do the following: To enable conversion tracking for all future links in a workspace, you can do the following: 1. Navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics). 2. Toggle the **Workspace-level Conversion Tracking** switch to enable conversion tracking for the workspace. Enabling conversion tracking for a workspace This option will enable conversion tracking in the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for all future links. If you don't want to enable conversion tracking for all your links in a workspace, you can also opt to enable it on a link-level. To enable conversion tracking for a specific link, open the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for a link and toggle the **Conversion Tracking** switch. Enabling conversion tracking for a link You can also use the `C` keyboard shortcut when inside the link builder to quickly enable conversion tracking for a given link. Alternatively, you can also enable conversion tracking programmatically via the [Dub API](/api-reference/introduction). All you need to do is pass `trackConversion: true` when creating or updating a link: ```javascript Node.js theme={null} const link = await dub.links.create({ url: "https://dub.co", trackConversion: true, }); ``` ```python Python theme={null} link = d.links.create(url="https://dub.co", track_conversion=True) ``` ```go Go theme={null} link, err := d.Links.Create(ctx, &dub.CreateLinkRequest{ URL: "https://dub.co", TrackConversion: true, }) ``` ```ruby Ruby theme={null} s.links.create_many( ::OpenApiSDK::Operations::CreateLinkRequest.new( url: "https://dub.co", track_conversion: true, ) ) ``` Then, you'd want to install the `@dub/analytics` script to your website to track conversion events. You can install the `@dub/analytics` script in several different ways: } href="/sdks/client-side/installation-guides/framer" horizontal /> You can **verify the installation** with the following tests: 1. Open the browser console and type in `_dubAnalytics` – if the script is installed correctly, you should see the `_dubAnalytics` object in the console. 2. Add the `?dub_id=test` query parameter to your website URL and make sure that the `dub_id` cookie is being set in your browser. If both of these checks pass, the script is installed correctly. Otherwise, please make sure: * The analytics script was added to the `` section of the page * If you're using a content delivery network (CDN), make sure to purge any cached content ## Installation To get started, simply install the [`@dub/better-auth` plugin](https://www.npmjs.com/package/@dub/better-auth) via your preferred package manager: ```bash npm theme={null} npm install @dub/better-auth ``` ```bash yarn theme={null} yarn add @dub/better-auth ``` ```bash pnpm theme={null} pnpm add @dub/better-auth ``` ```bash bun theme={null} bun add @dub/better-auth ``` Then, add the plugin to your better-auth config file: ```ts auth.ts theme={null} import { dubAnalytics } from "@dub/better-auth"; import { betterAuth } from "better-auth"; import { Dub } from "dub"; const dub = new Dub(); export const auth = betterAuth({ plugins: [ dubAnalytics({ dubClient: dub, }), ], }); ``` ## View your conversions Once you've completed the setup, all your tracked conversions will show up in [Dub Analytics](https://dub.co/analytics). We provide 3 different views to help you understand your conversions: * **Time-series**: A [time-series view](https://app.dub.co/dub/analytics?view=timeseries) of the number clicks, leads and sales. Time-series line chart * **Funnel chart**: A [funnel chart view](http://app.dub.co/analytics?view=funnel) visualizing the conversion & dropoff rates across the different steps in the conversion funnel (clicks → leads → sales). Funnel chart view showing the conversion & dropoff rates from clicks → leads → sales * **Real-time events stream**: A [real-time events stream](https://app.dub.co/events) of every single conversion event that occurs across all your links in your workspace. The Events Stream dashboard on Dub --- # Source: https://dub.co/docs/api-reference/endpoint/bulk-create-links.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bulk create links > Bulk create up to 100 links for the authenticated workspace. We currently do not send [webhook events](/concepts/webhooks/introduction) for bulk link creation. ## OpenAPI ````yaml post /links/bulk openapi: 3.0.3 info: title: Dub API description: >- Dub is the modern link attribution platform for short links, conversion tracking, and affiliate programs. version: 0.0.1 contact: name: Dub Support email: support@dub.co url: https://dub.co/api license: name: AGPL-3.0 license url: https://github.com/dubinc/dub/blob/main/LICENSE.md servers: - url: https://api.dub.co description: Production API security: [] paths: /links/bulk: post: tags: - Links summary: Bulk create links description: Bulk create up to 100 links for the authenticated workspace. operationId: bulkCreateLinks requestBody: content: application/json: schema: type: array items: type: object properties: url: description: The destination URL of the short link. example: https://google.com maxLength: 32000 type: string domain: description: >- The domain of the short link (without protocol). If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains). type: string maxLength: 190 key: description: >- The short link slug. If not provided, a random 7-character slug will be generated. type: string maxLength: 190 keyLength: description: >- The length of the short link slug. Defaults to 7 if not provided. When used with `prefix`, the total length of the key will be `prefix.length + keyLength`. type: number minimum: 3 maximum: 190 externalId: description: >- The ID of the link in your database. If set, it can be used to identify the link in future API requests (must be prefixed with 'ext_' when passed as a query parameter). This key is unique across your workspace. example: '123456' nullable: true type: string minLength: 1 maxLength: 255 tenantId: description: >- The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant. nullable: true type: string maxLength: 255 programId: nullable: true description: The ID of the program the short link is associated with. type: string partnerId: nullable: true description: The ID of the partner the short link is associated with. type: string prefix: description: >- The prefix of the short link slug for randomly-generated keys (e.g. if prefix is `/c/`, generated keys will be in the `/c/:key` format). Will be ignored if `key` is provided. type: string trackConversion: description: >- Whether to track conversions for the short link. Defaults to `false` if not provided. type: boolean archived: description: >- Whether the short link is archived. Defaults to `false` if not provided. type: boolean tagIds: description: The unique IDs of the tags assigned to the short link. example: - clux0rgak00011... anyOf: - type: string - type: array items: type: string tagNames: description: >- The unique name of the tags assigned to the short link (case insensitive). anyOf: - type: string - type: array items: type: string folderId: description: The unique ID existing folder to assign the short link to. nullable: true type: string comments: nullable: true description: The comments for the short link. type: string expiresAt: description: The date and time when the short link will expire at. nullable: true type: string expiredUrl: description: The URL to redirect to when the short link has expired. maxLength: 32000 nullable: true type: string password: nullable: true description: >- The password required to access the destination URL of the short link. type: string proxy: description: >- Whether the short link uses Custom Link Previews feature. Defaults to `false` if not provided. type: boolean title: description: >- The custom link preview title (og:title). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og nullable: true type: string description: description: >- The custom link preview description (og:description). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og nullable: true type: string image: description: >- The custom link preview image (og:image). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og nullable: true type: string video: nullable: true description: >- The custom link preview video (og:video). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og type: string rewrite: description: >- Whether the short link uses link cloaking. Defaults to `false` if not provided. type: boolean ios: description: >- The iOS destination URL for the short link for iOS device targeting. nullable: true type: string maxLength: 32000 android: description: >- The Android destination URL for the short link for Android device targeting. nullable: true type: string maxLength: 32000 geo: $ref: '#/components/schemas/linkGeoTargeting' doIndex: description: >- Allow search engines to index your short link. Defaults to `false` if not provided. Learn more: https://d.to/noindex type: boolean utm_source: description: >- The UTM source of the short link. If set, this will populate or override the UTM source in the destination URL. nullable: true type: string utm_medium: description: >- The UTM medium of the short link. If set, this will populate or override the UTM medium in the destination URL. nullable: true type: string utm_campaign: description: >- The UTM campaign of the short link. If set, this will populate or override the UTM campaign in the destination URL. nullable: true type: string utm_term: description: >- The UTM term of the short link. If set, this will populate or override the UTM term in the destination URL. nullable: true type: string utm_content: description: >- The UTM content of the short link. If set, this will populate or override the UTM content in the destination URL. nullable: true type: string ref: description: >- The referral tag of the short link. If set, this will populate or override the `ref` query parameter in the destination URL. nullable: true type: string webhookIds: description: >- An array of webhook IDs to trigger when the link is clicked. These webhooks will receive click event data. nullable: true type: array items: type: string testVariants: nullable: true minItems: 2 maxItems: 4 type: array items: type: object properties: url: type: string percentage: type: number minimum: 10 maximum: 90 required: - url - percentage description: >- An array of A/B test URLs and the percentage of traffic to send to each URL. example: - url: https://example.com/variant-1 percentage: 50 - url: https://example.com/variant-2 percentage: 50 testStartedAt: description: The date and time when the tests started. nullable: true type: string testCompletedAt: description: >- The date and time when the tests were or will be completed. nullable: true type: string publicStats: description: >- Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided. deprecated: true type: boolean tagId: description: >- Deprecated: Use `tagIds` instead. The unique ID of the tag assigned to the short link. deprecated: true nullable: true type: string required: - url responses: '200': description: The created links content: application/json: schema: type: array items: oneOf: - $ref: '#/components/schemas/LinkSchema' - $ref: '#/components/schemas/LinkErrorSchema' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': $ref: '#/components/responses/403' '404': $ref: '#/components/responses/404' '409': $ref: '#/components/responses/409' '410': $ref: '#/components/responses/410' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' '500': $ref: '#/components/responses/500' security: - token: [] components: schemas: linkGeoTargeting: description: >- Geo targeting information for the short link in JSON format `{[COUNTRY]: https://example.com }`. See https://d.to/geo for more information. nullable: true type: object additionalProperties: type: string maxLength: 32000 LinkSchema: type: object properties: id: type: string description: The unique ID of the short link. domain: type: string description: >- The domain of the short link. If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains). key: type: string description: >- The short link slug. If not provided, a random 7-character slug will be generated. url: type: string format: uri description: The destination URL of the short link. trackConversion: default: false description: Whether to track conversions for the short link. type: boolean externalId: nullable: true description: >- The ID of the link in your database. If set, it can be used to identify the link in future API requests (must be prefixed with 'ext_' when passed as a query parameter). This key is unique across your workspace. type: string tenantId: nullable: true description: >- The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant. type: string programId: nullable: true description: The ID of the program the short link is associated with. type: string partnerId: nullable: true description: The ID of the partner the short link is associated with. type: string archived: default: false description: Whether the short link is archived. type: boolean expiresAt: nullable: true description: >- The date and time when the short link will expire in ISO-8601 format. type: string expiredUrl: nullable: true description: The URL to redirect to when the short link has expired. type: string format: uri disabledAt: nullable: true description: >- The date and time when the short link was disabled. When a short link is disabled, it will redirect to its domain's not found URL, and its stats will be excluded from your overall stats. type: string password: nullable: true description: >- The password required to access the destination URL of the short link. type: string proxy: default: false description: Whether the short link uses Custom Link Previews feature. type: boolean title: nullable: true description: >- The title of the short link. Will be used for Custom Link Previews if `proxy` is true. type: string description: nullable: true description: >- The description of the short link. Will be used for Custom Link Previews if `proxy` is true. type: string image: nullable: true description: >- The image of the short link. Will be used for Custom Link Previews if `proxy` is true. type: string video: nullable: true description: >- The custom link preview video (og:video). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og type: string rewrite: default: false description: Whether the short link uses link cloaking. type: boolean doIndex: default: false description: Whether to allow search engines to index the short link. type: boolean ios: nullable: true description: The iOS destination URL for the short link for iOS device targeting. type: string android: nullable: true description: >- The Android destination URL for the short link for Android device targeting. type: string geo: nullable: true description: >- Geo targeting information for the short link in JSON format `{[COUNTRY]: https://example.com }`. See https://d.to/geo for more information. type: object additionalProperties: type: string format: uri publicStats: default: false description: Whether the short link's stats are publicly accessible. type: boolean tags: nullable: true description: The tags assigned to the short link. type: array items: $ref: '#/components/schemas/LinkTagSchemaOutput' folderId: nullable: true description: The unique ID of the folder assigned to the short link. type: string webhookIds: type: array items: type: string description: The IDs of the webhooks that the short link is associated with. comments: nullable: true description: The comments for the short link. type: string shortLink: type: string format: uri description: >- The full URL of the short link, including the https protocol (e.g. `https://dub.sh/try`). qrCode: type: string format: uri description: >- The full URL of the QR code for the short link (e.g. `https://api.dub.co/qr?url=https://dub.sh/try`). utm_source: nullable: true description: The UTM source of the short link. type: string utm_medium: nullable: true description: The UTM medium of the short link. type: string utm_campaign: nullable: true description: The UTM campaign of the short link. type: string utm_term: nullable: true description: The UTM term of the short link. type: string utm_content: nullable: true description: The UTM content of the short link. type: string testVariants: nullable: true minItems: 2 maxItems: 4 type: array items: type: object properties: url: type: string percentage: type: number minimum: 10 maximum: 90 required: - url - percentage additionalProperties: false description: >- An array of A/B test URLs and the percentage of traffic to send to each URL. example: - url: https://example.com/variant-1 percentage: 50 - url: https://example.com/variant-2 percentage: 50 testStartedAt: description: The date and time when the tests started. nullable: true type: string testCompletedAt: description: The date and time when the tests were or will be completed. nullable: true type: string userId: nullable: true description: The user ID of the creator of the short link. type: string workspaceId: type: string description: The workspace ID of the short link. clicks: default: 0 description: The number of clicks on the short link. type: number leads: default: 0 description: The number of leads the short link has generated. type: number conversions: default: 0 description: The number of leads that converted to paying customers. type: number sales: default: 0 description: >- The total number of sales (includes recurring sales) generated by the short link. type: number saleAmount: default: 0 description: >- The total dollar value of sales (in cents) generated by the short link. type: number lastClicked: nullable: true description: The date and time when the short link was last clicked. type: string createdAt: type: string description: The date and time when the short link was created. updatedAt: type: string description: The date and time when the short link was last updated. tagId: nullable: true description: >- Deprecated: Use `tags` instead. The unique ID of the tag assigned to the short link. deprecated: true type: string projectId: type: string description: >- Deprecated: Use `workspaceId` instead. The project ID of the short link. deprecated: true required: - id - domain - key - url - trackConversion - externalId - tenantId - programId - partnerId - archived - expiresAt - expiredUrl - disabledAt - password - proxy - title - description - image - video - rewrite - doIndex - ios - android - geo - publicStats - tags - folderId - webhookIds - comments - shortLink - qrCode - utm_source - utm_medium - utm_campaign - utm_term - utm_content - userId - workspaceId - clicks - leads - conversions - sales - saleAmount - lastClicked - createdAt - updatedAt - tagId - projectId additionalProperties: false title: Link LinkErrorSchema: type: object properties: link: description: The link that caused the error. error: type: string description: The error message. code: type: string enum: - bad_request - unauthorized - forbidden - exceeded_limit - not_found - conflict - invite_pending - invite_expired - unprocessable_entity - rate_limit_exceeded - internal_server_error description: The error code. required: - link - error - code additionalProperties: false title: LinkError LinkTagSchemaOutput: type: object properties: id: type: string description: The unique ID of the tag. name: type: string description: The name of the tag. color: type: string enum: - red - yellow - green - blue - purple - brown - pink description: The color of the tag. required: - id - name - color additionalProperties: false title: LinkTag responses: '400': description: >- The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). content: application/json: schema: x-speakeasy-name-override: BadRequest type: object properties: error: type: object properties: code: type: string enum: - bad_request description: A short code indicating the error code returned. example: bad_request message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#bad-request required: - code - message required: - error '401': description: >- Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. content: application/json: schema: x-speakeasy-name-override: Unauthorized type: object properties: error: type: object properties: code: type: string enum: - unauthorized description: A short code indicating the error code returned. example: unauthorized message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#unauthorized required: - code - message required: - error '403': description: >- The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. content: application/json: schema: x-speakeasy-name-override: Forbidden type: object properties: error: type: object properties: code: type: string enum: - forbidden description: A short code indicating the error code returned. example: forbidden message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#forbidden required: - code - message required: - error '404': description: The server cannot find the requested resource. content: application/json: schema: x-speakeasy-name-override: NotFound type: object properties: error: type: object properties: code: type: string enum: - not_found description: A short code indicating the error code returned. example: not_found message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#not-found required: - code - message required: - error '409': description: >- This response is sent when a request conflicts with the current state of the server. content: application/json: schema: x-speakeasy-name-override: Conflict type: object properties: error: type: object properties: code: type: string enum: - conflict description: A short code indicating the error code returned. example: conflict message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#conflict required: - code - message required: - error '410': description: >- This response is sent when the requested content has been permanently deleted from server, with no forwarding address. content: application/json: schema: x-speakeasy-name-override: InviteExpired type: object properties: error: type: object properties: code: type: string enum: - invite_expired description: A short code indicating the error code returned. example: invite_expired message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#invite-expired required: - code - message required: - error '422': description: >- The request was well-formed but was unable to be followed due to semantic errors. content: application/json: schema: x-speakeasy-name-override: UnprocessableEntity type: object properties: error: type: object properties: code: type: string enum: - unprocessable_entity description: A short code indicating the error code returned. example: unprocessable_entity message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#unprocessable-entity required: - code - message required: - error '429': description: >- The user has sent too many requests in a given amount of time ("rate limiting") content: application/json: schema: x-speakeasy-name-override: RateLimitExceeded type: object properties: error: type: object properties: code: type: string enum: - rate_limit_exceeded description: A short code indicating the error code returned. example: rate_limit_exceeded message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#rate-limit_exceeded required: - code - message required: - error '500': description: The server has encountered a situation it does not know how to handle. content: application/json: schema: x-speakeasy-name-override: InternalServerError type: object properties: error: type: object properties: code: type: string enum: - internal_server_error description: A short code indicating the error code returned. example: internal_server_error message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#internal-server_error required: - code - message required: - error securitySchemes: token: type: http description: Default authentication mechanism scheme: bearer x-speakeasy-example: DUB_API_KEY ```` --- # Source: https://dub.co/docs/api-reference/endpoint/bulk-delete-links.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bulk delete links > Bulk delete up to 100 links for the authenticated workspace. This is a destructive action and cannot be undone. Proceed with caution. Also, [webhook events](/concepts/webhooks/introduction) will not be triggered when using this endpoint. ## OpenAPI ````yaml delete /links/bulk openapi: 3.0.3 info: title: Dub API description: >- Dub is the modern link attribution platform for short links, conversion tracking, and affiliate programs. version: 0.0.1 contact: name: Dub Support email: support@dub.co url: https://dub.co/api license: name: AGPL-3.0 license url: https://github.com/dubinc/dub/blob/main/LICENSE.md servers: - url: https://api.dub.co description: Production API security: [] paths: /links/bulk: delete: tags: - Links summary: Bulk delete links description: Bulk delete up to 100 links for the authenticated workspace. operationId: bulkDeleteLinks parameters: - in: query name: linkIds schema: type: array items: type: string example: - clux0rgak00011... - clux0rgak00022... description: >- Comma-separated list of link IDs to delete. Maximum of 100 IDs. Non-existing IDs will be ignored. explode: false style: form required: true description: >- Comma-separated list of link IDs to delete. Maximum of 100 IDs. Non-existing IDs will be ignored. responses: '200': description: The deleted links count. content: application/json: schema: type: object properties: deletedCount: type: number description: The number of links deleted. required: - deletedCount additionalProperties: false '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': $ref: '#/components/responses/403' '404': $ref: '#/components/responses/404' '409': $ref: '#/components/responses/409' '410': $ref: '#/components/responses/410' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' '500': $ref: '#/components/responses/500' security: - token: [] components: responses: '400': description: >- The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). content: application/json: schema: x-speakeasy-name-override: BadRequest type: object properties: error: type: object properties: code: type: string enum: - bad_request description: A short code indicating the error code returned. example: bad_request message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#bad-request required: - code - message required: - error '401': description: >- Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. content: application/json: schema: x-speakeasy-name-override: Unauthorized type: object properties: error: type: object properties: code: type: string enum: - unauthorized description: A short code indicating the error code returned. example: unauthorized message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#unauthorized required: - code - message required: - error '403': description: >- The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. content: application/json: schema: x-speakeasy-name-override: Forbidden type: object properties: error: type: object properties: code: type: string enum: - forbidden description: A short code indicating the error code returned. example: forbidden message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#forbidden required: - code - message required: - error '404': description: The server cannot find the requested resource. content: application/json: schema: x-speakeasy-name-override: NotFound type: object properties: error: type: object properties: code: type: string enum: - not_found description: A short code indicating the error code returned. example: not_found message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#not-found required: - code - message required: - error '409': description: >- This response is sent when a request conflicts with the current state of the server. content: application/json: schema: x-speakeasy-name-override: Conflict type: object properties: error: type: object properties: code: type: string enum: - conflict description: A short code indicating the error code returned. example: conflict message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#conflict required: - code - message required: - error '410': description: >- This response is sent when the requested content has been permanently deleted from server, with no forwarding address. content: application/json: schema: x-speakeasy-name-override: InviteExpired type: object properties: error: type: object properties: code: type: string enum: - invite_expired description: A short code indicating the error code returned. example: invite_expired message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#invite-expired required: - code - message required: - error '422': description: >- The request was well-formed but was unable to be followed due to semantic errors. content: application/json: schema: x-speakeasy-name-override: UnprocessableEntity type: object properties: error: type: object properties: code: type: string enum: - unprocessable_entity description: A short code indicating the error code returned. example: unprocessable_entity message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#unprocessable-entity required: - code - message required: - error '429': description: >- The user has sent too many requests in a given amount of time ("rate limiting") content: application/json: schema: x-speakeasy-name-override: RateLimitExceeded type: object properties: error: type: object properties: code: type: string enum: - rate_limit_exceeded description: A short code indicating the error code returned. example: rate_limit_exceeded message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#rate-limit_exceeded required: - code - message required: - error '500': description: The server has encountered a situation it does not know how to handle. content: application/json: schema: x-speakeasy-name-override: InternalServerError type: object properties: error: type: object properties: code: type: string enum: - internal_server_error description: A short code indicating the error code returned. example: internal_server_error message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#internal-server_error required: - code - message required: - error securitySchemes: token: type: http description: Default authentication mechanism scheme: bearer x-speakeasy-example: DUB_API_KEY ```` --- # Source: https://dub.co/docs/concepts/links/bulk-operations.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bulk operations > Learn how to perform bulk operations on links. Dub allows you to perform bulk operations on links. This is particularly useful when you need to [create](/api-reference/endpoint/bulk-create-links), [update](/api-reference/endpoint/bulk-update-links), or [delete](/api-reference/endpoint/bulk-delete-links) multiple links at once without having to make multiple API requests. ## Bulk create links Bulk create allows you to create up to 100 links at once. Bulk link creation does not support [custom link previews](https://dub.co/help/article/custom-link-previews). Also, [webhook events](/concepts/webhooks/introduction) will not be triggered when using bulk link creation. ```javascript Node.js theme={null} import { Dub } from "dub"; export const dub = new Dub({ token: process.env.DUB_API_KEY, }); const result = await dub.links.createMany([ { url: "https://google.com", }, { url: "https://google.uk", }, ]); ``` ```go Go theme={null} package main import( "context" dubgo "github.com/dubinc/dub-go" "github.com/dubinc/dub-go/models/operations" "log" "os" ) func main() { ctx := context.Background() s := dubgo.New( dubgo.WithSecurity(os.Getenv("DUB_API_KEY")), ) } res, err := s.Links.CreateMany(ctx, []operations.RequestBody{ operations.RequestBody{ URL: "https://google.com", }, operations.RequestBody{ URL: "https://google.uk", }, }) ``` ```python Python theme={null} import os import dub from dub.models import operations d = dub.Dub( token=os.environ['DUB_API_KEY'], ) res = dub.links.create_many(request=[ { "url": "https://google.com", }, { "url": "https://google.uk", }, ]) ``` ```ruby Ruby theme={null} require 'dub' s = ::OpenApiSDK::Dub.new s.config_security( ::OpenApiSDK::Shared::Security.new( token: "DUB_API_KEY", ) ) req = [ ::OpenApiSDK::Operations::RequestBody.new( url: "https://google.com", ), ::OpenApiSDK::Operations::RequestBody.new( url: "https://example.uk" ), ] res = s.links.create_many(req) ``` ```php PHP theme={null} declare(strict_types=1); require 'vendor/autoload.php'; use Dub; use Dub\Models\Operations; $sdk = Dub\Dub::builder()->setSecurity('DUB_API_KEY')->build(); $request = [ new Operations\RequestBody( url: 'https://google.com', ), new Operations\RequestBody( url: 'https://google.uk', ), ]; $response = $sdk->links->createMany( request: $request ); ``` ```bash cURL theme={null} curl --request POST \ --url https://api.dub.co/links/bulk \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' --data '[ { "url": "https://google.com" }, { "url": "https://google.uk" } ]' ``` Check out the [full API reference for the link bulk creation endpoint](/api-reference/endpoint/bulk-create-links). ## Bulk update links Bulk update allows you to modify up to 100 links simultaneously **with the same data**. Some potential use cases: * Tagging multiple links at once * Setting the same expiration date for multiple links * Updating UTM parameters for multiple links You cannot update the domain or key of a link with this endpoint. Also, [webhook events](/concepts/webhooks/introduction) will not be triggered when using bulk link updates ```javascript Node.js theme={null} import { Dub } from "dub"; export const dub = new Dub({ token: process.env.DUB_API_KEY, }); const result = await dub.links.updateMany({ linkIds: ["clux0rgak00011...", "clux0rgak00022..."], data: { utm_source: "facebook", utm_medium: "cpc", }, }); ``` ```go Go theme={null} package main import( "context" dubgo "github.com/dubinc/dub-go" "github.com/dubinc/dub-go/models/operations" "log" "os" ) func main() { ctx := context.Background() s := dubgo.New( dubgo.WithSecurity(os.Getenv("DUB_API_KEY")), ) res, err := s.Links.UpdateMany(ctx, operations.BulkUpdateLinksRequestBody{ LinkIds: []string{ "clux0rgak00011...", "clux0rgak00022...", }, Data: map[string]string{ "utm_source": "facebook", "utm_medium": "cpc", }, }) } ``` ```python Python theme={null} import os import dub from dub.models import operations d = dub.Dub( token=os.environ['DUB_API_KEY'], ) res = dub.links.update_many(request={ "link_ids": [ "clux0rgak00011...", "clux0rgak00022...", ], "data": { "utm_source": "facebook", "utm_medium": "cpc", }, }) ``` ```ruby Ruby theme={null} require 'dub' s = ::OpenApiSDK::Dub.new s.config_security( ::OpenApiSDK::Shared::Security.new( token: "DUB_API_KEY", ) ) req = ::OpenApiSDK::Operations::BulkUpdateLinksRequestBody.new( link_ids: [ "clux0rgak00011...", "clux0rgak00022...", ], data: { "utm_source": "facebook", "utm_medium": "cpc", }, ) res = s.links.update_many(req) ``` ```php PHP theme={null} declare(strict_types=1); require 'vendor/autoload.php'; use Dub; use Dub\Models\Operations; $sdk = Dub\Dub::builder()->setSecurity('DUB_API_KEY')->build(); $response = $sdk->links->updateMany( linkIds: [ 'clux0rgak00011...', 'clux0rgak00022...', ], data: { "utm_source": "facebook", "utm_medium": "cpc", }, ); ``` ```bash cURL theme={null} curl --request PATCH \ --url https://api.dub.co/links/bulk \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{"link_ids": ["clux0rgak00011...", "clux0rgak00022..."], "data": {"utm_source": "facebook", "utm_medium": "cpc"}}' ``` Check out the [full API reference for the link bulk update endpoint](/api-reference/endpoint/bulk-update-links). ## Bulk delete links With bulk delete, you can delete up to 100 links at once. This is a destructive action and cannot be undone. Proceed with caution. Also, [webhook events](/concepts/webhooks/introduction) will not be triggered when using this endpoint. ```javascript Node.js theme={null} import { Dub } from "dub"; export const dub = new Dub({ token: process.env.DUB_API_KEY, }); const result = await dub.links.deleteMany({ linkIds: ["clux0rgak00011...", "clux0rgak00022..."], }); ``` ```go Go theme={null} package main import( "context" dubgo "github.com/dubinc/dub-go" "github.com/dubinc/dub-go/models/operations" "log" "os" ) func main() { ctx := context.Background() s := dubgo.New( dubgo.WithSecurity(os.Getenv("DUB_API_KEY")), ) res, err := s.Links.DeleteMany(ctx, operations.BulkDeleteLinksRequest{ LinkIds: []string{ "clux0rgak00011...", "clux0rgak00022...", }, }) } ``` ```python Python theme={null} import os import dub from dub.models import operations d = dub.Dub( token=os.environ['DUB_API_KEY'], ) res = dub.links.delete_many(request={ "link_ids": [ "clux0rgak00011...", "clux0rgak00022...", ], }) ``` ```ruby Ruby theme={null} require 'dub' s = ::OpenApiSDK::Dub.new s.config_security( ::OpenApiSDK::Shared::Security.new( token: "DUB_API_KEY", ) ) req = ::OpenApiSDK::Operations::BulkDeleteLinksRequest.new( link_ids: [ "clux0rgak00011...", "clux0rgak00022...", ], ) res = s.links.delete_many(req) ``` ```php PHP theme={null} declare(strict_types=1); require 'vendor/autoload.php'; use Dub; use Dub\Models\Operations; $sdk = Dub\Dub::builder()->setSecurity('DUB_API_KEY')->build(); $response = $sdk->links->deleteMany( linkIds: [ 'clux0rgak00011...', 'clux0rgak00022...', ] ); ``` ```bash cURL theme={null} curl --request DELETE \ --url https://api.dub.co/links/bulk?linkIds=clux0rgak00011... \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' ``` Check out the [full API reference for the link bulk delete endpoint](/api-reference/endpoint/bulk-delete-links). --- # Source: https://dub.co/docs/api-reference/endpoint/bulk-update-links.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Bulk update links > Bulk update up to 100 links with the same data for the authenticated workspace. This endpoint lets you update up to 100 links **with the same data**. Some potential use cases: * Tagging multiple links at once * Setting the same expiration date for multiple links * Updating UTM parameters for multiple links You cannot update the domain or key of a link with this endpoint. Also, [webhook events](/concepts/webhooks/introduction) will not be triggered when using this endpoint. ## OpenAPI ````yaml patch /links/bulk openapi: 3.0.3 info: title: Dub API description: >- Dub is the modern link attribution platform for short links, conversion tracking, and affiliate programs. version: 0.0.1 contact: name: Dub Support email: support@dub.co url: https://dub.co/api license: name: AGPL-3.0 license url: https://github.com/dubinc/dub/blob/main/LICENSE.md servers: - url: https://api.dub.co description: Production API security: [] paths: /links/bulk: patch: tags: - Links summary: Bulk update links description: >- Bulk update up to 100 links with the same data for the authenticated workspace. operationId: bulkUpdateLinks requestBody: content: application/json: schema: type: object properties: linkIds: default: [] maxItems: 100 type: array items: type: string description: >- The IDs of the links to update. Takes precedence over `externalIds`. externalIds: default: [] maxItems: 100 type: array items: type: string description: >- The external IDs of the links to update as stored in your database. data: type: object properties: url: description: The destination URL of the short link. example: https://google.com maxLength: 32000 type: string tenantId: description: >- The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant. nullable: true type: string maxLength: 255 programId: nullable: true description: The ID of the program the short link is associated with. type: string partnerId: nullable: true description: The ID of the partner the short link is associated with. type: string trackConversion: description: >- Whether to track conversions for the short link. Defaults to `false` if not provided. type: boolean archived: description: >- Whether the short link is archived. Defaults to `false` if not provided. type: boolean tagIds: description: The unique IDs of the tags assigned to the short link. example: - clux0rgak00011... anyOf: - type: string - type: array items: type: string tagNames: description: >- The unique name of the tags assigned to the short link (case insensitive). anyOf: - type: string - type: array items: type: string folderId: description: >- The unique ID existing folder to assign the short link to. nullable: true type: string comments: nullable: true description: The comments for the short link. type: string expiresAt: description: The date and time when the short link will expire at. nullable: true type: string expiredUrl: description: The URL to redirect to when the short link has expired. maxLength: 32000 nullable: true type: string password: nullable: true description: >- The password required to access the destination URL of the short link. type: string proxy: description: >- Whether the short link uses Custom Link Previews feature. Defaults to `false` if not provided. type: boolean title: description: >- The custom link preview title (og:title). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og nullable: true type: string description: description: >- The custom link preview description (og:description). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og nullable: true type: string image: description: >- The custom link preview image (og:image). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og nullable: true type: string video: nullable: true description: >- The custom link preview video (og:video). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og type: string rewrite: description: >- Whether the short link uses link cloaking. Defaults to `false` if not provided. type: boolean ios: description: >- The iOS destination URL for the short link for iOS device targeting. nullable: true type: string maxLength: 32000 android: description: >- The Android destination URL for the short link for Android device targeting. nullable: true type: string maxLength: 32000 geo: $ref: '#/components/schemas/linkGeoTargeting' doIndex: description: >- Allow search engines to index your short link. Defaults to `false` if not provided. Learn more: https://d.to/noindex type: boolean utm_source: description: >- The UTM source of the short link. If set, this will populate or override the UTM source in the destination URL. nullable: true type: string utm_medium: description: >- The UTM medium of the short link. If set, this will populate or override the UTM medium in the destination URL. nullable: true type: string utm_campaign: description: >- The UTM campaign of the short link. If set, this will populate or override the UTM campaign in the destination URL. nullable: true type: string utm_term: description: >- The UTM term of the short link. If set, this will populate or override the UTM term in the destination URL. nullable: true type: string utm_content: description: >- The UTM content of the short link. If set, this will populate or override the UTM content in the destination URL. nullable: true type: string ref: description: >- The referral tag of the short link. If set, this will populate or override the `ref` query parameter in the destination URL. nullable: true type: string webhookIds: description: >- An array of webhook IDs to trigger when the link is clicked. These webhooks will receive click event data. nullable: true type: array items: type: string testVariants: nullable: true minItems: 2 maxItems: 4 type: array items: type: object properties: url: type: string percentage: type: number minimum: 10 maximum: 90 required: - url - percentage description: >- An array of A/B test URLs and the percentage of traffic to send to each URL. example: - url: https://example.com/variant-1 percentage: 50 - url: https://example.com/variant-2 percentage: 50 testStartedAt: description: The date and time when the tests started. nullable: true type: string testCompletedAt: description: >- The date and time when the tests were or will be completed. nullable: true type: string publicStats: description: >- Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided. deprecated: true type: boolean tagId: description: >- Deprecated: Use `tagIds` instead. The unique ID of the tag assigned to the short link. deprecated: true nullable: true type: string required: - data responses: '200': description: The updated links content: application/json: schema: type: array items: $ref: '#/components/schemas/LinkSchema' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': $ref: '#/components/responses/403' '404': $ref: '#/components/responses/404' '409': $ref: '#/components/responses/409' '410': $ref: '#/components/responses/410' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' '500': $ref: '#/components/responses/500' security: - token: [] components: schemas: linkGeoTargeting: description: >- Geo targeting information for the short link in JSON format `{[COUNTRY]: https://example.com }`. See https://d.to/geo for more information. nullable: true type: object additionalProperties: type: string maxLength: 32000 LinkSchema: type: object properties: id: type: string description: The unique ID of the short link. domain: type: string description: >- The domain of the short link. If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains). key: type: string description: >- The short link slug. If not provided, a random 7-character slug will be generated. url: type: string format: uri description: The destination URL of the short link. trackConversion: default: false description: Whether to track conversions for the short link. type: boolean externalId: nullable: true description: >- The ID of the link in your database. If set, it can be used to identify the link in future API requests (must be prefixed with 'ext_' when passed as a query parameter). This key is unique across your workspace. type: string tenantId: nullable: true description: >- The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant. type: string programId: nullable: true description: The ID of the program the short link is associated with. type: string partnerId: nullable: true description: The ID of the partner the short link is associated with. type: string archived: default: false description: Whether the short link is archived. type: boolean expiresAt: nullable: true description: >- The date and time when the short link will expire in ISO-8601 format. type: string expiredUrl: nullable: true description: The URL to redirect to when the short link has expired. type: string format: uri disabledAt: nullable: true description: >- The date and time when the short link was disabled. When a short link is disabled, it will redirect to its domain's not found URL, and its stats will be excluded from your overall stats. type: string password: nullable: true description: >- The password required to access the destination URL of the short link. type: string proxy: default: false description: Whether the short link uses Custom Link Previews feature. type: boolean title: nullable: true description: >- The title of the short link. Will be used for Custom Link Previews if `proxy` is true. type: string description: nullable: true description: >- The description of the short link. Will be used for Custom Link Previews if `proxy` is true. type: string image: nullable: true description: >- The image of the short link. Will be used for Custom Link Previews if `proxy` is true. type: string video: nullable: true description: >- The custom link preview video (og:video). Will be used for Custom Link Previews if `proxy` is true. Learn more: https://d.to/og type: string rewrite: default: false description: Whether the short link uses link cloaking. type: boolean doIndex: default: false description: Whether to allow search engines to index the short link. type: boolean ios: nullable: true description: The iOS destination URL for the short link for iOS device targeting. type: string android: nullable: true description: >- The Android destination URL for the short link for Android device targeting. type: string geo: nullable: true description: >- Geo targeting information for the short link in JSON format `{[COUNTRY]: https://example.com }`. See https://d.to/geo for more information. type: object additionalProperties: type: string format: uri publicStats: default: false description: Whether the short link's stats are publicly accessible. type: boolean tags: nullable: true description: The tags assigned to the short link. type: array items: $ref: '#/components/schemas/LinkTagSchemaOutput' folderId: nullable: true description: The unique ID of the folder assigned to the short link. type: string webhookIds: type: array items: type: string description: The IDs of the webhooks that the short link is associated with. comments: nullable: true description: The comments for the short link. type: string shortLink: type: string format: uri description: >- The full URL of the short link, including the https protocol (e.g. `https://dub.sh/try`). qrCode: type: string format: uri description: >- The full URL of the QR code for the short link (e.g. `https://api.dub.co/qr?url=https://dub.sh/try`). utm_source: nullable: true description: The UTM source of the short link. type: string utm_medium: nullable: true description: The UTM medium of the short link. type: string utm_campaign: nullable: true description: The UTM campaign of the short link. type: string utm_term: nullable: true description: The UTM term of the short link. type: string utm_content: nullable: true description: The UTM content of the short link. type: string testVariants: nullable: true minItems: 2 maxItems: 4 type: array items: type: object properties: url: type: string percentage: type: number minimum: 10 maximum: 90 required: - url - percentage additionalProperties: false description: >- An array of A/B test URLs and the percentage of traffic to send to each URL. example: - url: https://example.com/variant-1 percentage: 50 - url: https://example.com/variant-2 percentage: 50 testStartedAt: description: The date and time when the tests started. nullable: true type: string testCompletedAt: description: The date and time when the tests were or will be completed. nullable: true type: string userId: nullable: true description: The user ID of the creator of the short link. type: string workspaceId: type: string description: The workspace ID of the short link. clicks: default: 0 description: The number of clicks on the short link. type: number leads: default: 0 description: The number of leads the short link has generated. type: number conversions: default: 0 description: The number of leads that converted to paying customers. type: number sales: default: 0 description: >- The total number of sales (includes recurring sales) generated by the short link. type: number saleAmount: default: 0 description: >- The total dollar value of sales (in cents) generated by the short link. type: number lastClicked: nullable: true description: The date and time when the short link was last clicked. type: string createdAt: type: string description: The date and time when the short link was created. updatedAt: type: string description: The date and time when the short link was last updated. tagId: nullable: true description: >- Deprecated: Use `tags` instead. The unique ID of the tag assigned to the short link. deprecated: true type: string projectId: type: string description: >- Deprecated: Use `workspaceId` instead. The project ID of the short link. deprecated: true required: - id - domain - key - url - trackConversion - externalId - tenantId - programId - partnerId - archived - expiresAt - expiredUrl - disabledAt - password - proxy - title - description - image - video - rewrite - doIndex - ios - android - geo - publicStats - tags - folderId - webhookIds - comments - shortLink - qrCode - utm_source - utm_medium - utm_campaign - utm_term - utm_content - userId - workspaceId - clicks - leads - conversions - sales - saleAmount - lastClicked - createdAt - updatedAt - tagId - projectId additionalProperties: false title: Link LinkTagSchemaOutput: type: object properties: id: type: string description: The unique ID of the tag. name: type: string description: The name of the tag. color: type: string enum: - red - yellow - green - blue - purple - brown - pink description: The color of the tag. required: - id - name - color additionalProperties: false title: LinkTag responses: '400': description: >- The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). content: application/json: schema: x-speakeasy-name-override: BadRequest type: object properties: error: type: object properties: code: type: string enum: - bad_request description: A short code indicating the error code returned. example: bad_request message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#bad-request required: - code - message required: - error '401': description: >- Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. content: application/json: schema: x-speakeasy-name-override: Unauthorized type: object properties: error: type: object properties: code: type: string enum: - unauthorized description: A short code indicating the error code returned. example: unauthorized message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#unauthorized required: - code - message required: - error '403': description: >- The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. content: application/json: schema: x-speakeasy-name-override: Forbidden type: object properties: error: type: object properties: code: type: string enum: - forbidden description: A short code indicating the error code returned. example: forbidden message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#forbidden required: - code - message required: - error '404': description: The server cannot find the requested resource. content: application/json: schema: x-speakeasy-name-override: NotFound type: object properties: error: type: object properties: code: type: string enum: - not_found description: A short code indicating the error code returned. example: not_found message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#not-found required: - code - message required: - error '409': description: >- This response is sent when a request conflicts with the current state of the server. content: application/json: schema: x-speakeasy-name-override: Conflict type: object properties: error: type: object properties: code: type: string enum: - conflict description: A short code indicating the error code returned. example: conflict message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#conflict required: - code - message required: - error '410': description: >- This response is sent when the requested content has been permanently deleted from server, with no forwarding address. content: application/json: schema: x-speakeasy-name-override: InviteExpired type: object properties: error: type: object properties: code: type: string enum: - invite_expired description: A short code indicating the error code returned. example: invite_expired message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#invite-expired required: - code - message required: - error '422': description: >- The request was well-formed but was unable to be followed due to semantic errors. content: application/json: schema: x-speakeasy-name-override: UnprocessableEntity type: object properties: error: type: object properties: code: type: string enum: - unprocessable_entity description: A short code indicating the error code returned. example: unprocessable_entity message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#unprocessable-entity required: - code - message required: - error '429': description: >- The user has sent too many requests in a given amount of time ("rate limiting") content: application/json: schema: x-speakeasy-name-override: RateLimitExceeded type: object properties: error: type: object properties: code: type: string enum: - rate_limit_exceeded description: A short code indicating the error code returned. example: rate_limit_exceeded message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#rate-limit_exceeded required: - code - message required: - error '500': description: The server has encountered a situation it does not know how to handle. content: application/json: schema: x-speakeasy-name-override: InternalServerError type: object properties: error: type: object properties: code: type: string enum: - internal_server_error description: A short code indicating the error code returned. example: internal_server_error message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#internal-server_error required: - code - message required: - error securitySchemes: token: type: http description: Default authentication mechanism scheme: bearer x-speakeasy-example: DUB_API_KEY ```` --- # Source: https://dub.co/docs/api-reference/endpoint/check-a-domain-availability.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Check the availability of one or more domains > Check if a domain name is available for purchase. You can check multiple domains at once. Checking a domain availability requires an [Enterprise plan](https://dub.co/enterprise) ## OpenAPI ````yaml get /domains/status openapi: 3.0.3 info: title: Dub API description: >- Dub is the modern link attribution platform for short links, conversion tracking, and affiliate programs. version: 0.0.1 contact: name: Dub Support email: support@dub.co url: https://dub.co/api license: name: AGPL-3.0 license url: https://github.com/dubinc/dub/blob/main/LICENSE.md servers: - url: https://api.dub.co description: Production API security: [] paths: /domains/status: get: tags: - Domains summary: Check the availability of one or more domains description: >- Check if a domain name is available for purchase. You can check multiple domains at once. operationId: checkDomainStatus parameters: - in: query name: domains schema: description: The domains to search. We only support .link domains for now. anyOf: - type: string - type: array items: type: string style: form explode: false required: true description: The domains to search. We only support .link domains for now. responses: '200': description: The domain status was retrieved. content: application/json: schema: type: array items: type: object properties: domain: type: string description: The domain name. available: type: boolean description: Whether the domain is available. price: nullable: true description: The price description. type: string premium: nullable: true description: Whether the domain is a premium domain. type: boolean required: - domain - available - price - premium additionalProperties: false '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '403': $ref: '#/components/responses/403' '404': $ref: '#/components/responses/404' '409': $ref: '#/components/responses/409' '410': $ref: '#/components/responses/410' '422': $ref: '#/components/responses/422' '429': $ref: '#/components/responses/429' '500': $ref: '#/components/responses/500' security: - token: [] components: responses: '400': description: >- The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). content: application/json: schema: x-speakeasy-name-override: BadRequest type: object properties: error: type: object properties: code: type: string enum: - bad_request description: A short code indicating the error code returned. example: bad_request message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#bad-request required: - code - message required: - error '401': description: >- Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. content: application/json: schema: x-speakeasy-name-override: Unauthorized type: object properties: error: type: object properties: code: type: string enum: - unauthorized description: A short code indicating the error code returned. example: unauthorized message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#unauthorized required: - code - message required: - error '403': description: >- The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. content: application/json: schema: x-speakeasy-name-override: Forbidden type: object properties: error: type: object properties: code: type: string enum: - forbidden description: A short code indicating the error code returned. example: forbidden message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#forbidden required: - code - message required: - error '404': description: The server cannot find the requested resource. content: application/json: schema: x-speakeasy-name-override: NotFound type: object properties: error: type: object properties: code: type: string enum: - not_found description: A short code indicating the error code returned. example: not_found message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#not-found required: - code - message required: - error '409': description: >- This response is sent when a request conflicts with the current state of the server. content: application/json: schema: x-speakeasy-name-override: Conflict type: object properties: error: type: object properties: code: type: string enum: - conflict description: A short code indicating the error code returned. example: conflict message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#conflict required: - code - message required: - error '410': description: >- This response is sent when the requested content has been permanently deleted from server, with no forwarding address. content: application/json: schema: x-speakeasy-name-override: InviteExpired type: object properties: error: type: object properties: code: type: string enum: - invite_expired description: A short code indicating the error code returned. example: invite_expired message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: https://dub.co/docs/api-reference/errors#invite-expired required: - code - message required: - error '422': description: >- The request was well-formed but was unable to be followed due to semantic errors. content: application/json: schema: x-speakeasy-name-override: UnprocessableEntity type: object properties: error: type: object properties: code: type: string enum: - unprocessable_entity description: A short code indicating the error code returned. example: unprocessable_entity message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#unprocessable-entity required: - code - message required: - error '429': description: >- The user has sent too many requests in a given amount of time ("rate limiting") content: application/json: schema: x-speakeasy-name-override: RateLimitExceeded type: object properties: error: type: object properties: code: type: string enum: - rate_limit_exceeded description: A short code indicating the error code returned. example: rate_limit_exceeded message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#rate-limit_exceeded required: - code - message required: - error '500': description: The server has encountered a situation it does not know how to handle. content: application/json: schema: x-speakeasy-name-override: InternalServerError type: object properties: error: type: object properties: code: type: string enum: - internal_server_error description: A short code indicating the error code returned. example: internal_server_error message: x-speakeasy-error-message: true type: string description: A human readable explanation of what went wrong. example: The requested resource was not found. doc_url: type: string description: >- A link to our documentation with more details about this error code example: >- https://dub.co/docs/api-reference/errors#internal-server_error required: - code - message required: - error securitySchemes: token: type: http description: Default authentication mechanism scheme: bearer x-speakeasy-example: DUB_API_KEY ```` --- # Source: https://dub.co/docs/conversions/leads/clerk.md > ## Documentation Index > Fetch the complete documentation index at: https://dub.co/docs/llms.txt > Use this file to discover all available pages before exploring further. # Clerk > Learn how to track lead conversion events with Clerk and Dub Conversion tracking requires a [Business plan](https://dub.co/pricing) subscription or higher. When it comes to [conversion tracking](/conversions/quickstart), a `lead` event happens when a user performs an action that indicates interest in your product or service. This could be anything from: * Signing up for an account * Booking a demo meeting * Joining a mailing list A diagram showing how lead events are tracked in the conversion funnel In this guide, we will be focusing on tracking new user sign-ups for a SaaS application that uses Clerk for user authentication. ## Prerequisites First, you'll need to enable conversion tracking for your Dub links to be able to start tracking conversions: If you're using [Dub Partners](/partners/quickstart), you can skip this step since partner links will have conversion tracking enabled by default. To enable conversion tracking for all future links in a workspace, you can do the following: To enable conversion tracking for all future links in a workspace, you can do the following: 1. Navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics). 2. Toggle the **Workspace-level Conversion Tracking** switch to enable conversion tracking for the workspace. Enabling conversion tracking for a workspace This option will enable conversion tracking in the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for all future links. If you don't want to enable conversion tracking for all your links in a workspace, you can also opt to enable it on a link-level. To enable conversion tracking for a specific link, open the [Dub Link Builder](https://dub.co/help/article/dub-link-builder) for a link and toggle the **Conversion Tracking** switch. Enabling conversion tracking for a link You can also use the `C` keyboard shortcut when inside the link builder to quickly enable conversion tracking for a given link. Alternatively, you can also enable conversion tracking programmatically via the [Dub API](/api-reference/introduction). All you need to do is pass `trackConversion: true` when creating or updating a link: ```javascript Node.js theme={null} const link = await dub.links.create({ url: "https://dub.co", trackConversion: true, }); ``` ```python Python theme={null} link = d.links.create(url="https://dub.co", track_conversion=True) ``` ```go Go theme={null} link, err := d.Links.Create(ctx, &dub.CreateLinkRequest{ URL: "https://dub.co", TrackConversion: true, }) ``` ```ruby Ruby theme={null} s.links.create_many( ::OpenApiSDK::Operations::CreateLinkRequest.new( url: "https://dub.co", track_conversion: true, ) ) ``` Then, you'd want to install the `@dub/analytics` script to your website to track conversion events. You can install the `@dub/analytics` script in several different ways: } href="/sdks/client-side/installation-guides/framer" horizontal /> You can **verify the installation** with the following tests: 1. Open the browser console and type in `_dubAnalytics` – if the script is installed correctly, you should see the `_dubAnalytics` object in the console. 2. Add the `?dub_id=test` query parameter to your website URL and make sure that the `dub_id` cookie is being set in your browser. If both of these checks pass, the script is installed correctly. Otherwise, please make sure: * The analytics script was added to the `` section of the page * If you're using a content delivery network (CDN), make sure to purge any cached content ## Configure Clerk Next, configure Clerk to track lead conversion events when a new user signs up. Here's a quick video showing how to do this: