diff --git a/apps/web/package.json b/apps/web/package.json
index fd4faa0c1..11a6977ca 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -14,6 +14,7 @@
"copy:pdfjs": "node ../../scripts/copy-pdfjs.cjs"
},
"dependencies": {
+ "@documenso/api": "*",
"@documenso/assets": "*",
"@documenso/ee": "*",
"@documenso/lib": "*",
diff --git a/apps/web/src/app/(dashboard)/settings/tokens/page.tsx b/apps/web/src/app/(dashboard)/settings/tokens/page.tsx
new file mode 100644
index 000000000..8951098c4
--- /dev/null
+++ b/apps/web/src/app/(dashboard)/settings/tokens/page.tsx
@@ -0,0 +1,74 @@
+import { DateTime } from 'luxon';
+
+import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
+import { getUserTokens } from '@documenso/lib/server-only/public-api/get-all-user-tokens';
+import { Button } from '@documenso/ui/primitives/button';
+
+import DeleteTokenDialog from '~/components/(dashboard)/settings/token/delete-token-dialog';
+import { LocaleDate } from '~/components/formatter/locale-date';
+import { ApiTokenForm } from '~/components/forms/token';
+
+export default async function ApiTokensPage() {
+ const { user } = await getRequiredServerComponentSession();
+
+ const tokens = await getUserTokens({ userId: user.id });
+
+ return (
+
+
API Tokens
+
+
+ On this page, you can create new API tokens and manage the existing ones.
+
+
+
+
+
+
+
+
+
Your existing tokens
+
+ {tokens.length === 0 && (
+
+
+ Your tokens will be shown here once you create them.
+
+
+ )}
+
+ {tokens.length > 0 && (
+
+ {tokens.map((token) => (
+
+
+
+
{token.name}
+
+
+ Created on
+
+ {token.expires ? (
+
+ Expires on
+
+ ) : (
+
+ Token doesn't have an expiration date
+
+ )}
+
+
+
+
+
+
+
+
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/apps/web/src/app/api/v1/openapi/page.tsx b/apps/web/src/app/api/v1/openapi/page.tsx
new file mode 100644
index 000000000..ca5c3a5ed
--- /dev/null
+++ b/apps/web/src/app/api/v1/openapi/page.tsx
@@ -0,0 +1,3 @@
+'use client';
+
+export { OpenApiDocsPage as default } from '@documenso/api/v1/api-documentation';
diff --git a/apps/web/src/components/(dashboard)/layout/profile-dropdown.tsx b/apps/web/src/components/(dashboard)/layout/profile-dropdown.tsx
index a767b9700..6b9ec7fdf 100644
--- a/apps/web/src/components/(dashboard)/layout/profile-dropdown.tsx
+++ b/apps/web/src/components/(dashboard)/layout/profile-dropdown.tsx
@@ -3,6 +3,7 @@
import Link from 'next/link';
import {
+ Braces,
CreditCard,
FileSpreadsheet,
Lock,
@@ -98,6 +99,13 @@ export const ProfileDropdown = ({ user }: ProfileDropdownProps) => {
+
+
+
+ API Tokens
+
+
+
{isBillingEnabled && (
diff --git a/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx b/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx
index 572c91c76..e87c47b67 100644
--- a/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx
+++ b/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx
@@ -5,7 +5,7 @@ import type { HTMLAttributes } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
-import { CreditCard, Lock, User, Users } from 'lucide-react';
+import { Braces, CreditCard, Lock, User, Users } from 'lucide-react';
import { useFeatureFlags } from '@documenso/lib/client-only/providers/feature-flag';
import { cn } from '@documenso/ui/lib/utils';
@@ -64,6 +64,19 @@ export const DesktopNav = ({ className, ...props }: DesktopNavProps) => {
+
+
+
+
{isBillingEnabled && (
+
+
+
+
{isBillingEnabled && (