Skip to content

Funding Account Tokens API

The Funding Account Tokens API allows you to generate secure, short-lived JWT tokens for accessing TreasuryPath's funding accounts hosted page. These tokens enable your users to link and manage external bank accounts for debit transactions.

Endpoints


Generate Funding Account Token

Generate a secure token that grants access to the funding accounts hosted page. Users can link bank accounts and provide mandate information through the hosted page workflow.

Endpoint

POST /api/v1/hosted_page_tokens

Headers

Authorization: Bearer {api_key}
Content-Type: application/json

Request Body

Parameter Type Required Description
entity_id string Yes ID of the entity
purpose string Yes Must be "funding_accounts"
return_url string No URL to redirect the user to after completing the flow. Must match a trusted domain.

Example Request

curl --request POST \
  --url https://api.treasurypath.com/api/v1/hosted_page_tokens \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "entity_id": "Z2lkOi8vYXBwL0VudGl0eS8xMjM",
    "purpose": "funding_accounts",
    "return_url": "https://app.example.com/accounts/linked"
  }'

Success Response (201 Created)

{
  "data": {
    "token": "eyJhbGciOiJIUzI1NiJ9.eyJjb21wYW55X2lkIjoiZ2lkOi8vYXBwL0NvbXBhbnkvMSIsImVudGl0eV9pZCI6ImdpZDovL2FwcC9FbnRpdHkvMTIzIiwicHVycG9zZSI6ImZ1bmRpbmdfYWNjb3VudHMiLCJleHAiOjE3MDk4NTEyMDB9.abc123",
    "purpose": "funding_accounts",
    "return_url": "https://yourapp.com/funding-accounts/complete"
  }
}

return_url in response

The return_url field is only present in the response when a valid return_url was provided in the request and passed trusted domain validation.

Response Fields

Field Type Description
token string Authentication token valid for 2 hours. Pass this as a URL parameter to the funding accounts hosted page.
purpose string Purpose of the token ("funding_accounts")
return_url string (Optional) The validated return URL. Only present when a valid return_url was provided.

Token Properties

  • Expiration: Tokens expire 2 hours after generation
  • Format: Secure JWT token
  • Scope: Limited to funding account operations for the specified entity
  • Usage: Pass as URL parameter to {TREASURYPATH_HOSTED_URL}/funding-accounts?token={token}

Error Responses

400 Bad Request - Missing Entity ID

{
  "errors": [
    {
      "field": "entity_id",
      "message": "Entity ID is required"
    }
  ]
}

400 Bad Request - Missing Purpose

{
  "errors": [
    {
      "field": "purpose",
      "message": "Purpose is required"
    }
  ]
}

400 Bad Request - Invalid Purpose

{
  "errors": [
    {
      "field": "purpose",
      "message": "Invalid purpose"
    }
  ]
}

401 Unauthorized - Invalid API Key

{
  "errors": [
    {
      "field": "token",
      "message": "Missing or invalid token"
    }
  ]
}

403 Forbidden - Purpose Category Mismatch

{
  "errors": [
    {
      "field": "purpose",
      "message": "Purpose must be a hosted_page category"
    }
  ]
}

404 Not Found - Entity Not Found

{
  "errors": [
    {
      "field": "entity_id",
      "message": "Entity not found or not accessible in this company"
    }
  ]
}

422 Unprocessable Entity - Untrusted Return URL Domain

{
  "errors": [
    {
      "field": "return_url",
      "message": "URL domain is not in the trusted domains list"
    }
  ]
}

Resolution: Add the return URL's domain to your workspace's trusted domains configuration via the GraphQL upsertTrustedDomainConfig mutation. See Trusted Domains for details.

422 Unprocessable Entity - Entity Does Not Belong to Company

{
  "errors": [
    {
      "field": "entity",
      "message": "Entity does not belong to this company"
    }
  ]
}

422 Unprocessable Entity - Missing Multi-Currency Account

{
  "errors": [
    {
      "field": "entity_id",
      "message": "Multi-currency account not found for this entity. Please create an account first."
    }
  ]
}

Resolution: Ensure the entity has a multi-currency account enabled before generating funding account tokens. See Multi-Currency Enablement for details.

422 Unprocessable Entity - Untrusted Return URL

{
  "errors": [
    {
      "field": "return_url",
      "message": "URL domain is not in the trusted domains list"
    }
  ]
}

Resolution: Add the return URL's domain to your workspace's trusted domains. If no trusted domains are configured, return_url is silently ignored.


Prerequisites

Before generating funding account tokens, ensure:

  1. Multi-Currency Account Enabled - The entity must have an active multi-currency account. See Enable Multi-Currency.

  2. Entity Ownership - The entity must belong to your company.

  3. Valid API Key - Your API key must have appropriate permissions.

  4. Trusted Domains Configured (if using return_url) - Your workspace must have a trusted domain configuration. See Trusted Domains.


Trusted Domains

To use the return_url parameter, your workspace must have a trusted domain configuration. Trusted domains define which external URLs are allowed as redirect targets after a user completes a hosted page flow.

How It Works

  • When return_url is provided and the workspace has trusted domains configured, the URL's domain is validated against the allowlist.
  • If the domain is trusted, the return_url is included in the JWT token and the API response.
  • If the domain is not trusted, a 422 error is returned.
  • If no trusted domain config exists for the workspace, return_url is silently ignored (no error, but the URL is not included in the token or response).

Wildcard Support

Trusted domains support wildcard patterns:

Pattern Matches Does Not Match
app.example.com https://app.example.com/callback https://other.example.com/callback
*.example.com https://app.example.com/callback, https://staging.example.com/callback https://example.com/callback

Managing Trusted Domains

Configure trusted domains via the GraphQL upsertTrustedDomainConfig mutation:

mutation {
  upsertTrustedDomainConfig(input: {
    domains: ["app.example.com", "*.staging.example.com"]
  }) {
    trustedDomainConfig {
      id
      domains
    }
    errors {
      field
      messages
    }
  }
}

Token Security

Best Practices

  1. Secure Transmission
  2. Use HTTPS for all API requests
  3. Transmit tokens only via secure channels
  4. Never log tokens or expose them in error messages

  5. Fresh Tokens

  6. Generate a new token for each user session
  7. Don't cache or reuse tokens across sessions
  8. Tokens automatically expire after 2 hours

  9. Token Validation

  10. Expired or invalid tokens will be rejected by the hosted page
  11. Users will see an error message if token validation fails
  12. Generate a new token if the previous one expired

Token Lifecycle

Generate Token (API)
   └─> Valid for 2 hours
       └─> Redirect user to hosted page
           └─> Hosted page validates token
               ├─> Valid: User accesses funding accounts
               └─> Invalid/Expired: Error displayed

Hosted Page Features

The funding accounts hosted page provides:

Account Linking

  • Secure bank account selection via Plaid
  • Multiple account support per entity

Mandate Collection

  • Email address collection
  • Signatory name collection
  • Debit authorization (US ACH Debit)

Account Management

  • View all linked accounts
  • Monitor account status

Integration Flow

Typical Implementation

  1. User Initiates Linking
  2. User clicks "Add Bank Account" in your application
  3. Your backend calls the token generation endpoint
  4. You receive a token with 2-hour expiration

  5. Redirect to Hosted Page

  6. Redirect user to: {TREASURYPATH_HOSTED_URL}/funding-accounts?token={token}
  7. User completes bank account linking
  8. User provides mandate information

  9. Account Linked

  10. Account is created and processed
  11. Mandate information is stored

Code Example

// Backend: Generate token
async function generateFundingAccountToken(entityId, returnUrl) {
  const body = {
    entity_id: entityId,
    purpose: 'funding_accounts'
  };

  // Optionally include return_url (requires trusted domains to be configured)
  if (returnUrl) {
    body.return_url = returnUrl;
  }

  const response = await fetch('https://api.treasurypath.com/api/v1/hosted_page_tokens', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${YOUR_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(body)
  });

  const data = await response.json();
  return data.data.token;
}

// Frontend: Redirect user
async function linkBankAccount(entityId) {
  const token = await generateFundingAccountToken(
    entityId,
    'https://yourapp.com/funding-accounts/complete'
  );
  window.location.href = `{TREASURYPATH_HOSTED_URL}/funding-accounts?token=${token}`;
}

See Also