Authentication

Secure your API access with JWT Bearer tokens, OAuth2 social login, passkeys, magic links, and two-factor authentication. Complete guide to the OrbNET authentication flow.

Security

Authentication

Secure every API request with industry-standard authentication. OrbNET supports JWT Bearer tokens, OAuth2 social login, passkeys, magic links, two-factor authentication, and API keys -- giving you flexible, production-grade security for any integration.

0
Auth Methods
0
Token Lifetime
0
2FA Support
0
Passkey Standard

Authentication Methods Overview

OrbNET provides multiple authentication strategies. Choose the one that fits your application architecture and security requirements.

JWT Bearer Tokens

The primary authentication method. Exchange email and password for an access token and refresh token pair. Access tokens expire after 24 hours and can be renewed silently with the refresh token.

OAuth2 Social Login

Let users authenticate with their existing Google or Apple accounts. Token exchange returns the same JWT pair, providing a seamless sign-in experience without password management.

Passkeys / WebAuthn

Passwordless authentication using FIDO2 hardware keys or platform biometrics. The most secure option, resistant to phishing and credential stuffing attacks.

Magic Links

Send a one-time login link to the user's email. No password required. Ideal for low-friction onboarding and infrequent access patterns.

Two-Factor Authentication

Add a second layer of security with TOTP codes from apps like Google Authenticator or Authy. Can be combined with any primary authentication method.

API Key Authentication

Static API keys for server-to-server integrations with OrbGuard Labs. Generated from the dashboard, passed via the X-API-Key header.


Authentication Flow

Follow these steps to authenticate and make your first protected API request.


JWT Bearer Token Authentication

The primary authentication method for all OrbNET API requests. Exchange user credentials for a JWT access token and refresh token.

Login

POST/api/v1/auth/login

Authenticate with email and password to receive JWT access and refresh tokens.

Authentication:No Auth Required
ParameterTypeRequiredDescription
emailstring RequiredThe user's registered email address.
passwordstring RequiredThe user's password. Minimum 8 characters.
totp_codestringOptionalOnly for accounts with two-factor authentication: the 6-digit authenticator code or a recovery code. Without it, such an account gets the requires_2fa challenge described in Sign In When 2FA Is Enabled.
curl -X POST https://api.orbai.world/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "your_password"
  }'
200Successful authentication
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2...",
    "expiresAt": "2026-02-08T12:00:00Z",
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "user"
    }
  }
}
401Invalid credentials
{
  "success": false,
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "The email or password you entered is incorrect."
  }
}
429Too many login attempts
{
  "success": false,
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many login attempts. Please try again later.",
    "details": {
      "retryAfter": 300
    }
  }
}

Accounts with two-factor authentication

For an account with 2FA, a correct password without totp_code returns HTTP 200 with "requires_2fa": true and a pending_token, and no tokens. Finish the sign-in at POST /api/v1/auth/2fa/complete, or post the password again with totp_code. See Sign In When 2FA Is Enabled.

Using the Access Token

Once authenticated, include the JWT access token in the Authorization header of every protected request.

curl https://api.orbai.world/api/v1/users/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Token Security

Never expose your access tokens in client-side code, URLs, or version control. Store tokens in HTTP-only cookies, secure local storage, or your platform's keychain. Tokens passed in URLs or query parameters will be rejected.

Refreshing Tokens

Access tokens expire after 24 hours. Use the refresh token to obtain a new access token without requiring the user to re-enter credentials.

POST/api/v1/auth/refresh

Exchange a valid refresh token for a new access token and refresh token pair.

Authentication:No Auth Required
ParameterTypeRequiredDescription
refreshTokenstring RequiredThe refresh token received from the login or previous refresh response.
curl -X POST https://api.orbai.world/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2..."
  }'
200Tokens refreshed successfully
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...(new)",
    "refreshToken": "dGhpcyBpcyBhIG5ldyBy...(new)",
    "expiresAt": "2026-02-09T12:00:00Z",
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "user"
    }
  }
}
401Refresh token expired or invalid
{
  "success": false,
  "error": {
    "code": "INVALID_REFRESH_TOKEN",
    "message": "The refresh token is expired or has been revoked. Please log in again."
  }
}

Refresh Token Rotation

Each call to the refresh endpoint returns a new refresh token and invalidates the previous one. This is called refresh token rotation and prevents token replay attacks. Always store and use the latest refresh token.

Logout

Invalidate the current session and revoke the refresh token.

POST/api/v1/auth/logout

Invalidate the current access and refresh tokens, ending the user session.

Authentication:Bearer Token
ParameterTypeRequiredDescription
refreshTokenstring RequiredThe refresh token to revoke.
curl -X POST https://api.orbai.world/api/v1/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2..."
  }'
200Successfully logged out
{
  "success": true,
  "data": {
    "message": "Successfully logged out."
  }
}

User Registration

Create a new OrbVPN account with email and password. New accounts require email verification before full API access is granted.

POST/api/v1/auth/register

Register a new user account with email, password, and display name.

Authentication:No Auth Required
ParameterTypeRequiredDescription
emailstring RequiredA valid email address. Must not already be registered.
passwordstring RequiredPassword with minimum 8 characters, including uppercase, lowercase, and a number.
namestring RequiredThe user's display name.
curl -X POST https://api.orbai.world/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "newuser@example.com",
    "password": "SecureP@ss123",
    "name": "Jane Doe"
  }'
201Account created successfully
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2...",
    "expiresAt": "2026-02-08T12:00:00Z",
    "user": {
      "id": "usr_def456",
      "email": "newuser@example.com",
      "role": "user"
    },
    "emailVerificationRequired": true
  }
}
409Email already registered
{
  "success": false,
  "error": {
    "code": "EMAIL_EXISTS",
    "message": "An account with this email address already exists."
  }
}

Email Verification

After registration, a verification email is sent automatically. The user must click the verification link or enter the code to activate their account. Some protected endpoints may return limited data until verification is complete.


OAuth2 Social Login

Allow users to authenticate with their existing Google or Apple accounts. The client obtains an OAuth token from the identity provider, then exchanges it with OrbNET for a JWT token pair.

Google OAuth

POST/api/v1/auth/oauth/google

Authenticate using a Google OAuth2 ID token.

Authentication:No Auth Required
ParameterTypeRequiredDescription
idTokenstring RequiredThe Google ID token obtained from Google Sign-In on the client.
curl -X POST https://api.orbai.world/api/v1/auth/oauth/google \
  -H "Content-Type: application/json" \
  -d '{
    "idToken": "eyJhbGciOiJSUzI1NiIs...(Google ID token)"
  }'
200Google OAuth successful
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2...",
    "expiresAt": "2026-02-08T12:00:00Z",
    "user": {
      "id": "usr_ggl789",
      "email": "user@gmail.com",
      "role": "user"
    },
    "isNewUser": false
  }
}

Apple OAuth

POST/api/v1/auth/oauth/apple

Authenticate using an Apple Sign-In authorization code.

Authentication:No Auth Required
ParameterTypeRequiredDescription
authorizationCodestring RequiredThe authorization code from Apple Sign-In.
identityTokenstring RequiredThe identity token from Apple Sign-In.
namestringOptionalThe user's full name (only provided on first sign-in with Apple).
curl -X POST https://api.orbai.world/api/v1/auth/oauth/apple \
  -H "Content-Type: application/json" \
  -d '{
    "authorizationCode": "c1a2b3d4e5f6...",
    "identityToken": "eyJhbGciOiJSUzI1NiIs...",
    "name": "Jane Doe"
  }'
200Apple OAuth successful
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2...",
    "expiresAt": "2026-02-08T12:00:00Z",
    "user": {
      "id": "usr_apl012",
      "email": "user@privaterelay.appleid.com",
      "role": "user"
    },
    "isNewUser": true
  }
}

OAuth Token Flow

Both Google and Apple OAuth endpoints create a new OrbVPN account on first use (indicated by isNewUser: true) and link subsequent logins to the same account. The returned JWT tokens work identically to those from email/password login.


Passkeys / WebAuthn

Passwordless authentication using the FIDO2/WebAuthn standard. Supports hardware security keys, platform biometrics (Touch ID, Face ID, Windows Hello), and cross-device authentication. The flow requires two round trips: a begin call to get a challenge from the server, followed by a finish call with the signed challenge from the authenticator.

Phishing Resistant

Passkeys are bound to the origin domain and cannot be used on fraudulent sites.

Fast Authentication

One-tap biometric login without typing passwords or waiting for codes.

No Shared Secrets

Private keys never leave the authenticator device. The server only stores public keys.

Register a Passkey

Step 1: Begin Registration

POST/api/v1/auth/passkeys/register/begin

Request a WebAuthn registration challenge from the server.

Authentication:Bearer Token
curl -X POST https://api.orbai.world/api/v1/auth/passkeys/register/begin \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
200Registration challenge created
{
  "success": true,
  "data": {
    "publicKey": {
      "challenge": "dGhpcyBpcyBhIGNoYWxsZW5nZQ...",
      "rp": { "name": "OrbVPN", "id": "orbvpn.com" },
      "user": {
        "id": "dXNyX2FiYzEyMw...",
        "name": "user@example.com",
        "displayName": "Jane Doe"
      },
      "pubKeyCredParams": [
        { "type": "public-key", "alg": -7 },
        { "type": "public-key", "alg": -257 }
      ],
      "timeout": 60000,
      "attestation": "none",
      "authenticatorSelection": {
        "residentKey": "preferred",
        "userVerification": "preferred"
      }
    }
  }
}

Step 2: Finish Registration

POST/api/v1/auth/passkeys/register/finish

Complete passkey registration by submitting the signed credential from the authenticator.

Authentication:Bearer Token
ParameterTypeRequiredDescription
credentialobject RequiredThe PublicKeyCredential object returned by navigator.credentials.create(), serialized to JSON.
curl -X POST https://api.orbai.world/api/v1/auth/passkeys/register/finish \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "credential": {
      "id": "a1b2c3d4e5...",
      "rawId": "YTFiMmMzZDRl...",
      "type": "public-key",
      "response": {
        "attestationObject": "o2NmbXRk...",
        "clientDataJSON": "eyJ0eXBlI..."
      }
    }
  }'
200Passkey registered successfully
{
  "success": true,
  "data": {
    "credentialId": "a1b2c3d4e5...",
    "message": "Passkey registered successfully."
  }
}

Authenticate with a Passkey

Step 1: Begin Login

POST/api/v1/auth/passkeys/login/begin

Request a WebAuthn authentication challenge.

Authentication:No Auth Required
ParameterTypeRequiredDescription
emailstringOptionalOptional. The user's email to narrow down credential selection.
curl -X POST https://api.orbai.world/api/v1/auth/passkeys/login/begin \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'
200Authentication challenge created
{
  "success": true,
  "data": {
    "publicKey": {
      "challenge": "YW5vdGhlciBjaGFsbGVuZ2U...",
      "timeout": 60000,
      "rpId": "orbvpn.com",
      "allowCredentials": [
        {
          "type": "public-key",
          "id": "a1b2c3d4e5..."
        }
      ],
      "userVerification": "preferred"
    }
  }
}

Step 2: Finish Login

POST/api/v1/auth/passkeys/login/finish

Complete passkey authentication by submitting the signed assertion.

Authentication:No Auth Required
ParameterTypeRequiredDescription
credentialobject RequiredThe PublicKeyCredential object returned by navigator.credentials.get(), serialized to JSON.
curl -X POST https://api.orbai.world/api/v1/auth/passkeys/login/finish \
  -H "Content-Type: application/json" \
  -d '{
    "credential": {
      "id": "a1b2c3d4e5...",
      "rawId": "YTFiMmMzZDRl...",
      "type": "public-key",
      "response": {
        "authenticatorData": "SZYN5YgO...",
        "clientDataJSON": "eyJ0eXBlI...",
        "signature": "MEUCIQC...",
        "userHandle": "dXNyX2FiYzEyMw..."
      }
    }
  }'
200Passkey authentication successful
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2...",
    "expiresAt": "2026-02-08T12:00:00Z",
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "user"
    }
  }
}

Discoverable Credentials

If no email is provided in the begin step, the browser will display all discoverable credentials (resident keys) for the domain. This enables a truly passwordless, username-less experience.


Send a one-time login link to the user's email. Clicking the link authenticates the user and returns JWT tokens. No password required. If the account has two-factor authentication, the link alone is not enough: verifying it returns a requires_2fa challenge, and the user finishes with their code.

POST/api/v1/auth/magic-link/request

Send a one-time magic login link to the specified email address.

Authentication:No Auth Required
ParameterTypeRequiredDescription
emailstring RequiredThe email address to send the magic link to. Must be a registered account.
curl -X POST https://api.orbai.world/api/v1/auth/magic-link/request \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'
200Magic link sent
{
  "success": true,
  "data": {
    "message": "A magic link has been sent to your email address.",
    "expiresIn": 600
  }
}

Security Notice

Magic links expire after 10 minutes and can only be used once. For security, the API always returns a success response regardless of whether the email is registered, to prevent account enumeration.

When the user clicks the magic link in their email, they are redirected to your application with a token query parameter. Exchange this token for JWT credentials.

POST/api/v1/auth/magic-link/verify

Verify a magic link token and return JWT credentials, or a requires_2fa challenge when the account has two-factor authentication.

Authentication:No Auth Required
ParameterTypeRequiredDescription
tokenstring RequiredThe one-time token from the magic link URL query parameter.
device_idstringOptionalStable device identifier for a device session (counts against the plan's device limit). Send platform web instead for a browser session that uses no device slot.
platformstringOptionalOne of: ios, android, windows, macos, linux, web.
device_namestringOptionalHuman-readable device name.
curl -X POST https://api.orbai.world/api/v1/auth/magic-link/verify \
  -H "Content-Type: application/json" \
  -d '{"token": "ml_abc123def456...", "platform": "web"}'
200Magic link verified; the account has no two-factor authentication
{
  "success": true,
  "data": {
    "user": {
      "id": 1,
      "email": "user@example.com",
      "role": "USER"
    },
    "tokens": {
      "access_token": "eyJhbGciOiJIUzI1NiIs...",
      "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2...",
      "access_token_expires_at": "2026-02-08T12:00:00Z",
      "refresh_token_expires_at": "2026-03-08T12:00:00Z",
      "token_type": "Bearer"
    }
  }
}
200Magic link verified; the account has two-factor authentication, so no tokens are issued yet
{
  "success": true,
  "data": {
    "requires_2fa": true,
    "user": {
      "email": "user@example.com"
    },
    "two_factor": {
      "pending_token": "eyJhbGciOiJIUzI1NiIs...",
      "expires_in": 300,
      "methods": ["totp", "recovery_code"]
    }
  }
}
401Magic link token expired or invalid
{
  "success": false,
  "error": {
    "code": "INVALID_MAGIC_LINK",
    "message": "This magic link has expired or has already been used."
  }
}

The link is used up only when sign-in completes

When a code is owed, the magic link is not used up at verify time. It is spent when POST /api/v1/auth/2fa/complete succeeds, so a user who closes the code prompt can still use the same link while it is valid. A link signs in once, even if it was verified twice.


Two-Factor Authentication (2FA)

Add a second layer of verification using Time-based One-Time Passwords (TOTP). Compatible with authenticator apps such as Google Authenticator, Authy, and 1Password.

Once 2FA is on, every way of signing in asks for the code: password login, magic links, Google and Apple sign-in, passkeys used without user verification, and the Telegram mini-app. A passkey that verified the user (biometric or PIN) already counts as two factors. QR sign-in approved from a phone that is already signed in counts too.

Manage 2FA

The management endpoints need a signed-in user (bearer token). Full request and response details are in the Two-Factor Authentication reference.

EndpointBodyPurpose
POST /api/v1/security/totp/setupnoneReturns secret, qr_code_url and recovery_codes. 2FA is not on yet.
POST /api/v1/security/totp/enable{"code": "123456"}Turns 2FA on after the first valid authenticator code.
POST /api/v1/security/totp/disable{"code": "123456"}Turns 2FA off.
POST /api/v1/security/totp/recovery-codes{"totp_code": "123456"}Issues a new set of recovery codes and invalidates the old ones.
curl -X POST https://api.orbai.world/api/v1/security/totp/setup \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
200TOTP secret generated. Show the QR code, then confirm with the enable endpoint.
{
  "success": true,
  "data": {
    "secret": "JBSWY3DPEHPK3PXP",
    "qr_code_url": "otpauth://totp/OrbVPN:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=OrbVPN",
    "recovery_codes": ["a1b2-c3d4e5", "f6a7-b8c9d0"]
  }
}

Store recovery codes securely

Recovery codes are shown once. Each one works once, in place of an authenticator code, if the user loses their device.

Sign In When 2FA Is Enabled

A sign-in whose first factor is correct, but which still owes the code, returns HTTP 200 with a challenge and no tokens:

{
  "success": true,
  "data": {
    "requires_2fa": true,
    "user": { "email": "user@example.com" },
    "two_factor": {
      "pending_token": "eyJhbGciOiJIUzI1NiIs...",
      "expires_in": 300,
      "methods": ["totp", "recovery_code"]
    }
  }
}

Ask the user for the code and send it with the pending token:

POST/api/v1/auth/2fa/complete

Finish a sign-in that answered requires_2fa. Returns the same AuthResponse the original sign-in method would have returned.

Authentication:No Auth Required
ParameterTypeRequiredDescription
pending_tokenstring Requiredtwo_factor.pending_token from the challenge. Valid for 300 seconds; completes one sign-in.
codestring RequiredThe 6-digit authenticator code, or a recovery code (xxxx-xxxxxx). A recovery code works once.
curl -X POST https://api.orbai.world/api/v1/auth/2fa/complete \
  -H "Content-Type: application/json" \
  -d '{"pending_token": "eyJhbGciOiJIUzI1NiIs...", "code": "123456"}'
HTTPcodeWhat the client should do
200noneSigned in. The body is the normal AuthResponse (user, tokens, subscription).
401TWO_FACTOR_INVALIDThe code is wrong. Keep the pending token and ask again.
429TWO_FACTOR_LOCKEDMore than 5 attempts in 10 minutes for this account. Wait, then try again.
401TWO_FACTOR_PENDING_INVALIDThe pending token expired, was already used, or is not valid, or the account changed since it was issued (password reset, reseller-created account claimed, or two-factor authentication turned off). Start the sign-in again.
413PAYLOAD_TOO_LARGEThe body is over 16 KiB. Send only pending_token and code.
422VALIDATION_ERRORpending_token or code is missing, pending_token is over 8192 characters, or code is not 6 to 64 characters.
403DEVICE_LIMIT_EXCEEDEDDevice sign-in with every slot in use. Free a device with device_logout_token, then send the same pending token again with a valid code.
401Wrong code (Problem Details body)
{
  "type": "https://api.orbai.world/errors/TWO_FACTOR_INVALID",
  "title": "Invalid Code",
  "status": 401,
  "detail": "The two-factor code is incorrect",
  "code": "TWO_FACTOR_INVALID"
}

One request instead of two, for password login

Password login also accepts the code directly: post email, password and totp_code to POST /api/v1/auth/login. A wrong totp_code returns 401 TWO_FACTOR_INVALID, and the same 5-attempt limit applies.

The pending token is not an access token

The API refuses a pending token as a bearer token on every authenticated route. It carries no account data and only works at POST /api/v1/auth/2fa/complete.


API Key Authentication

For server-to-server integrations, particularly with the OrbGuard Labs API, you can use static API keys instead of JWT tokens. API keys are generated from the OrbVPN dashboard and do not expire unless revoked.

ANY/api/v1/guard/*

OrbGuard Labs endpoints accept API key authentication via the X-API-Key header.

Authentication:API Key
curl https://guard.orbai.world/api/v1/intelligence/check \
  -H "X-API-Key: orbk_live_abc123def456ghi789..."  \
  -H "Content-Type: application/json" \
  -d '{
    "indicator": "suspicious-domain.com",
    "type": "domain"
  }'

API Key Security

API keys carry the full permissions of the account that created them. Never embed API keys in client-side code, mobile apps, or public repositories. Use environment variables or a secrets manager for server-side storage. Rotate keys regularly from the OrbVPN dashboard.


Security Best Practices

Use HTTPS Everywhere

All API requests must use HTTPS. HTTP requests are rejected. TLS 1.2+ is required for all connections to the OrbNET platform.

Store Tokens Securely

Use HTTP-only cookies, platform keychains, or encrypted storage. Never store tokens in localStorage on web apps or embed them in URLs.

Implement Token Refresh

Build automatic token refresh logic into your client. On receiving a 401, attempt a silent refresh before prompting the user to re-authenticate.

Enable 2FA for Sensitive Accounts

Require two-factor authentication for admin accounts and users with elevated privileges. It significantly reduces the risk of account takeover.

Rotate API Keys

Periodically rotate API keys from the dashboard. Revoke any keys that may have been exposed. Use separate keys for development and production.

Monitor for Anomalies

Watch for unusual authentication patterns such as logins from new locations, rapid token refreshes, or simultaneous sessions from different regions.


Error Reference

Common authentication error codes and how to handle them.

INVALID_CREDENTIALS

Email or password is incorrect. Prompt the user to check their credentials and try again.

TOKEN_EXPIRED

The access token has expired. Use the refresh token to obtain a new access token.

INVALID_REFRESH_TOKEN

The refresh token is expired or revoked. The user must log in again with their credentials.

requires_2fa

Not an error: a 200 response with no tokens. The account has 2FA enabled. Send the pending token and the user's code to POST /api/v1/auth/2fa/complete.

TWO_FACTOR_INVALID

The authenticator or recovery code is wrong (401). Keep the pending token and ask the user again.

TWO_FACTOR_LOCKED

Too many wrong codes for this account (429): at most 5 attempts in 10 minutes. Wait before trying again.

TWO_FACTOR_PENDING_INVALID

The pending token expired (after 5 minutes), was already used, is not valid, or predates a password reset, the claim of a reseller-created account, or two-factor authentication being turned off (401). Start the sign-in again.

EMAIL_NOT_VERIFIED

The account exists but the email has not been verified. Redirect the user to the verification flow.

RATE_LIMITED

Too many authentication attempts. Respect the retryAfter value in the error response before retrying.

ACCOUNT_LOCKED

The account has been temporarily locked due to suspicious activity. Contact support or wait for the lockout period to expire.

INVALID_API_KEY

The provided API key is invalid, expired, or revoked. Generate a new key from the OrbVPN dashboard.


Need Help?

If you are experiencing authentication issues, check our troubleshooting guide or contact developer support. For account-specific issues, visit the support portal.

Start Building with OrbNET

You are now ready to authenticate and make secure API requests. Explore the full OrbNET API reference to manage VPN connections, users, subscriptions, and more.

Explore OrbNET API