Skip to content

API reference

Authentication

Log in, refresh tokens, sessions, email verification and password reset.

19 operationsBase URL https://packetexchange.io/api/v1Postman collection

Create an account

POST/api/v1/auth/register

Access
Public. No key needed.
Rate limit
200 requests per hour

Creates the account, emails a verification link and signs you in. acceptTerms must be true. An invite code, when given, adds test credit once the email is verified. Returns the same session payload as login.

Request body (application/json)

  • emailrequired

    string (email)

  • passwordrequired

    string

    max 128 chars
  • contactNamerequired

    string

    max 255 chars
  • companyName

    string

    max 255 chars
  • country

    string

    max 2 chars
  • inviteCode

    string

  • acceptTermsrequired

    boolean

    One of true

Response 201

  • datarequired

    object

  • accessTokenrequired

    string · data.accessToken

    JWT access token. Send as Authorization: Bearer <token>.
  • refreshTokenrequired

    string · data.refreshToken

    Refresh token (7 days). Also set as an httpOnly cookie scoped to /api/v1/auth.
  • expiresInrequired

    integer · data.expiresIn

    Access-token lifetime in seconds (900)
  • userrequired

    object · data.user

  • idrequired

    string (uuid) · data.user.id

  • emailrequired

    string (email) · data.user.email

  • contactNamerequired

    string · data.user.contactName

  • companyNamerequired

    string | null · data.user.companyName

  • jobTitlerequired

    string | null · data.user.jobTitle

  • phonerequired

    string | null · data.user.phone

  • countryrequired

    string | null · data.user.country

    ISO-3166-1 alpha-2
  • timezonerequired

    string · data.user.timezone

  • companyLogoUrlrequired

    string | null · data.user.companyLogoUrl

  • avatarUrlrequired

    string | null · data.user.avatarUrl

  • rolerequired

    string · data.user.role

    One of user, admin
  • statusrequired

    string · data.user.status

    One of active, suspended
  • accountKindrequired

    string · data.user.accountKind

  • balancerequired

    money · data.user.balance

    USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • testCreditrequired

    money · data.user.testCredit

    Sandbox credit, spendable only by test API keys USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • emailVerifiedAtrequired

    string (date-time) | null · data.user.emailVerifiedAt

    ISO-8601 timestamp (UTC)
  • pendingEmailrequired

    string | null · data.user.pendingEmail

    An address change waiting for confirmation
  • verificationStatusrequired

    string · data.user.verificationStatus

    One of unverified, verified
  • kycStatusrequired

    string · data.user.kycStatus

    One of not_started, pending, verified, rejected
  • totpEnabledrequired

    boolean · data.user.totpEnabled

    Two-factor authentication is on
  • taxIdrequired

    string | null · data.user.taxId

  • taxCountryrequired

    string | null · data.user.taxCountry

  • payoutMethodrequired

    string | null · data.user.payoutMethod

  • onboardingGoalrequired

    string | null · data.user.onboardingGoal

  • onboardingDismissedrequired

    boolean · data.user.onboardingDismissed

  • onboardingSeenrequired

    boolean · data.user.onboardingSeen

  • emailNotificationsOptOutrequired

    boolean · data.user.emailNotificationsOptOut

  • switchStatusrequired

    string · data.user.switchStatus

    One of none, active, past_due, canceled, comp
  • createdAtrequired

    string (date-time) · data.user.createdAt

    ISO-8601 timestamp (UTC)
  • updatedAtrequired

    string (date-time) · data.user.updatedAt

    ISO-8601 timestamp (UTC)

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Log in with email and password

POST/api/v1/auth/login

Access
Public. No key needed.
Rate limit
20 requests per 5 minutes

Returns an access token, a refresh token and your profile. When two-factor authentication is on, returns { mfaRequired: true, mfaToken } instead: complete the login with POST /auth/2fa/verify. Repeated failures lock the account temporarily.

Request body (application/json)

  • emailrequired

    string (email)

  • passwordrequired

    string

    max 128 chars

Response 200

  • datarequired

    object

  • accessToken

    string · data.accessToken

    JWT access token. Send as Authorization: Bearer <token>.
  • refreshToken

    string · data.refreshToken

    Refresh token (7 days). Also set as an httpOnly cookie scoped to /api/v1/auth.
  • expiresIn

    integer · data.expiresIn

    Access-token lifetime in seconds (900)
  • user

    object · data.user

    Same fields as AccountProfile, shown earlier on this page.
  • mfaRequired

    boolean · data.mfaRequired

    One of true
  • mfaToken

    string · data.mfaToken

    Short-lived (5 minutes) token to send with a TOTP code to POST /auth/2fa/verify

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Complete a two-factor login

POST/api/v1/auth/2fa/verify

Access
Public. No key needed.
Rate limit
15 requests per 5 minutes

Exchanges the mfaToken from login plus an authenticator (or backup) code for a session.

Request body (application/json)

  • mfaTokenrequired

    string

    From the login response
  • coderequired

    string

    6-digit authenticator code, or one of your backup codes

Response 200

  • datarequired

    object

    Same fields as AuthSession, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Refresh an access token

POST/api/v1/auth/refresh

Access
Public. No key needed.
Rate limit
100 requests per second (the default)

Reads the refresh token from the httpOnly cookie, or from the body for non-browser clients. Rotates the refresh token: store the new one. Cross-site browser requests are refused with CSRF_BLOCKED; a missing token is MISSING_TOKEN.

Request body (application/json)

  • refreshToken

    string

Response 200

  • datarequired

    object

  • accessTokenrequired

    string · data.accessToken

    JWT access token. Send as Authorization: Bearer <token>.
  • refreshTokenrequired

    string · data.refreshToken

    Refresh token (7 days). Also set as an httpOnly cookie scoped to /api/v1/auth.
  • expiresInrequired

    integer · data.expiresIn

    Access-token lifetime in seconds (900)

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.
  • AlsoMISSING_TOKEN, CSRF_BLOCKED

Log out the current session

POST/api/v1/auth/logout

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Revokes only this session (other devices stay signed in) and clears the refresh cookie.

Response 200

  • datarequired

    object

  • messagerequired

    string · data.message

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List your active sessions

GET/api/v1/auth/sessions

Access
Dashboard session. API keys are refused with 403. Use a login access token.
Rate limit
100 requests per second (the default)

Signed-in devices, most recently seen first. current marks the one making the request.

Response 200

  • datarequired

    object[]

  • idrequired

    string (uuid) · data[].id

  • iprequired

    string | null · data[].ip

  • userAgentrequired

    string | null · data[].userAgent

  • createdAtrequired

    string (date-time) · data[].createdAt

    ISO-8601 timestamp (UTC)
  • lastSeenAtrequired

    string (date-time) | null · data[].lastSeenAt

    ISO-8601 timestamp (UTC)
  • currentrequired

    boolean · data[].current

    True for the session making this request (matched via the refresh token)

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Sign out one session

DELETE/api/v1/auth/sessions/{id}

Access
Dashboard session. API keys are refused with 403. Use a login access token.
Rate limit
100 requests per second (the default)

Parameters

  • idrequired

    path · string

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 404NOT_FOUND: no such resource on your account.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Sign out every other session

POST/api/v1/auth/sessions/revoke-others

Access
Dashboard session. API keys are refused with 403. Use a login access token.
Rate limit
100 requests per second (the default)

Keeps the current session. Needs the refresh token (cookie or body) to know which session is current; without it the answer is NO_SESSION.

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.
  • AlsoNO_SESSION

Verify your email address

POST/api/v1/auth/verify-email

Access
Public. No key needed.
Rate limit
100 requests per second (the default)

Consumes the token from the verification email. Any invite-code test credit is added at this point.

Request body (application/json)

  • tokenrequired

    string

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Confirm an email address change

POST/api/v1/auth/confirm-email-change

Access
Public. No key needed.
Rate limit
10 requests per 10 minutes

Finishes a change requested with POST /account/email, using the token from the link sent to the NEW address. Public on purpose: the single-use token is the proof, so the link works on any device.

Request body (application/json)

  • tokenrequired

    string

    The token from the confirmation link sent to the new address

Response 200

  • datarequired

    object

  • emailrequired

    string (email) · data.email

    The address now on the account

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Resend the verification email

POST/api/v1/auth/resend-verification

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Redeem an invite code after sign-up

POST/api/v1/auth/invite/redeem

Access
API key. Full-access keys only; not reachable by scoped keys.
Rate limit
10 requests per 10 minutes

For social sign-ups, or a code mistyped at registration. ok: false carries the reason. When the email is not verified yet, the credit is held (pending: true) and added on verification.

Request body (application/json)

  • coderequired

    string

    max 64 chars

Response 200

  • datarequired

    object

  • okrequired

    boolean · data.ok

  • amount

    money · data.amount

    Test credit granted USD as a decimal string with exactly 6 places, e.g. "0.012500".
  • pending

    boolean · data.pending

    True when the credit waits for email verification
  • reason

    string · data.reason

    Why the code was not applied

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Resend a verification email by address

POST/api/v1/auth/resend-verification-public

Access
Public. No key needed.
Rate limit
5 requests per hour

For users whose link expired and who cannot sign in. Always answers the same way, whether or not the account exists.

Request body (application/json)

  • emailrequired

    string (email)

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Request a password reset email

POST/api/v1/auth/forgot-password

Access
Public. No key needed.
Rate limit
5 requests per hour

Always answers the same way, whether or not the account exists.

Request body (application/json)

  • emailrequired

    string (email)

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Reset your password with a reset token

POST/api/v1/auth/reset-password

Access
Public. No key needed.
Rate limit
15 requests per hour

Request body (application/json)

  • tokenrequired

    string

  • newPasswordrequired

    string

    max 128 chars

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Change your password

POST/api/v1/auth/change-password

Access
Dashboard session. API keys are refused with 403. Use a login access token.
Rate limit
100 requests per second (the default)

Requires the current password. Signs out every session, including this one once its access token expires, and emails a confirmation.

Request body (application/json)

  • currentPasswordrequired

    string

  • newPasswordrequired

    string

    At least 8 characters and different from the current password

Response 200

  • datarequired

    object

    Same fields as Message, shown earlier on this page.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 401UNAUTHORIZED: missing, invalid, expired or revoked credential.
  • 403FORBIDDEN: not allowed - a scoped key lacks the scope, or the endpoint is session-only.
  • 409CONFLICT (or a code-specific 409): the change clashes with existing state.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

List the social login providers that are enabled

GET/api/v1/auth/oauth/providers

Access
Public. No key needed.
Rate limit
100 requests per second (the default)

Response 200

  • datarequired

    object

  • googlerequired

    boolean · data.google

  • linkedinrequired

    boolean · data.linkedin

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Start a social login

GET/api/v1/auth/oauth/{provider}/start

Access
Public. No key needed.
Rate limit
100 requests per second (the default)

A browser navigation, not an API call. Redirects to the provider; next is a same-site path to land on afterwards.

Parameters

  • providerrequired

    path · string

    One of google, linkedin
  • next

    query · string

    Relative path to open after signing in, e.g. /dashboard

Response 302

Redirect to the provider, or to /login?oauth_error=unavailable when the provider is not configured.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.

Finish a social login (provider callback)

GET/api/v1/auth/oauth/{provider}/callback

Access
Public. No key needed.
Rate limit
100 requests per second (the default)

Called by the provider after consent. Signs the browser in and redirects into the app, or to /login?oauth_error=... on failure.

Parameters

  • providerrequired

    path · string

    One of google, linkedin
  • code

    query · string

  • state

    query · string

  • error

    query · string

Response 302

Redirect into the app when signed in, or to /login with an oauth_error reason.

Errors

  • 400VALIDATION_ERROR, INVALID_INPUT or BAD_REQUEST. For VALIDATION_ERROR, error.details is an array of { path, message }.
  • 404NOT_FOUND: no such resource on your account.
  • 429RATE_LIMITED: slow down and retry after the Retry-After seconds.
  • 500INTERNAL_ERROR: unexpected failure. Quote X-Request-Id to support.