Asset Tap
Generate 3D models from text prompts


Providers

Included AI providers, available models, and how to add your own custom providers.

Asset Tap uses a data-driven provider system where AI providers are defined entirely through YAML configuration files. No code changes are needed to add, remove, or modify providers.

Included Provider

Asset Tap ships with pre-configured support for fal.ai, providing both text-to-image and image-to-3D models.

Text-to-Image Models

ModelDescription
Nano Banana 2Gemini 3.1 Flash Image -- reasoning-guided generation (default)
Nano BananaGoogle Imagen 3-based image generation -- fast and affordable
Nano Banana ProPremium Google Imagen 3 -- higher quality with aspect ratio control
FLUX.2 DevOpen-source FLUX.2 with tunable guidance and steps
FLUX.2 ProPremium FLUX.2 -- best quality, zero-config

Image-to-3D Models

ModelDescription
TRELLIS 2Native 3D generative model -- fast and versatile (default)
Hunyuan3D ProTencent Hunyuan3D v3.1 Pro -- high quality 3D generation
Meshy v6Production-ready 3D models with PBR textures

Tip: Your fal.ai Dashboard shows all generation requests, results, and costs. This is the source of truth for your usage and a handy way to recover past outputs.


Adding Custom Providers

You can add support for any AI provider by creating a YAML configuration file. No code changes required.

Quick Start

Create a YAML file with your provider's API details:

provider:
  id: "my-provider"
  name: "My Provider"
  description: "Custom AI provider"
  env_vars: ["MY_API_KEY"]
  base_url: "https://api.example.com"
  api_key_url: "https://example.com/keys"

text_to_image:
  - id: "my-model"
    name: "My Model"
    description: "Fast image generation"
    endpoint: "/generate"
    method: POST
    request:
      headers:
        Authorization: "Bearer ${MY_API_KEY}"
        Content-Type: "application/json"
      body:
        prompt: "${prompt}"
    response:
      response_type: Json
      field: "image_url"

Where to Put Your Config

For personal use (no rebuild needed):

Place the YAML file in your user config directory:

  • macOS: ~/Library/Application Support/asset-tap/providers/my-provider.yaml
  • Linux: ~/.config/asset-tap/providers/my-provider.yaml
  • Windows: %APPDATA%/asset-tap/providers/my-provider.yaml

Restart the application and your provider will appear automatically.

To embed in the binary (requires rebuild):

  1. Add the file to providers/my-provider.yaml in the source tree
  2. Run make build -- the include_dir! macro discovers all *.yaml files automatically

Authentication

List required environment variables in env_vars. The provider won't appear as available until all are set.

provider:
  env_vars: ["MY_API_KEY", "MY_SECRET"]

Use ${ENV_VAR} syntax in request templates:

request:
  headers:
    Authorization: "Bearer ${MY_API_KEY}"

In the GUI, set API keys in Settings. For the CLI, use environment variables or a .env file.

Response Types

JSON -- Extract a URL from a JSON response:

response:
  response_type: Json
  field: "data.images[0].url"    # JSONPath expression

Polling -- For async APIs that queue jobs:

response:
  response_type: polling
  polling:
    status_field: "status_url"        # Field in submit response containing the status check URL
    status_check_field: "status"      # Field in status response to check
    success_value: "COMPLETED"
    failure_value: "FAILED"
    response_url_field: "response_url"  # Field containing URL to fetch final result
    response_envelope_field: "response" # Field in result that wraps the actual output
    result_field: "images[0].url"       # JSONPath to extract from the output
    interval_ms: 1000
    max_attempts: 120

Binary / Base64 -- For direct file responses:

response:
  response_type: Binary

# or base64-encoded in JSON:
response:
  response_type: Base64
  field: "artifacts[0].base64"

Image-to-3D Models

Image-to-3D models use ${image_url} instead of ${prompt}. Asset Tap automatically uploads the image and substitutes the public URL:

image_to_3d:
  - id: "my-3d-model"
    name: "My 3D Model"
    endpoint: "/3d/generate"
    method: POST
    request:
      headers:
        Authorization: "Key ${MY_API_KEY}"
        Content-Type: "application/json"
      body:
        image_url: "${image_url}"
    response:
      response_type: polling
      polling:
        status_field: "id"
        status_check_field: "status"
        success_value: "succeeded"
        result_field: "model_glb.url"
        interval_ms: 2000
        max_attempts: 300

Upload Configuration

Required when models use ${image_url}. The upload section is nested under provider::

provider:
  id: "my-provider"
  # ... other provider fields ...
  upload:
    endpoint: "/storage/upload/initiate"
    method: POST
    request:
      type: initiate_then_put    # or "multipart"
      headers:
        Authorization: "Key ${MY_API_KEY}"
        Content-Type: "application/json"
      initiate_body:
        file_name: "image.png"
        content_type: "image/png"
    response:
      upload_url_field: "upload_url"
      file_url_field: "file_url"

Testing Your Provider

# 1. Verify the provider loads and config is valid
asset-tap --list-providers

# 2. Verify it appears in mock mode (confirms config parsing)
asset-tap --mock -p my-provider -y "test prompt"

# 3. Test with real API (required to validate response parsing)
asset-tap -p my-provider -y "a red cube"

Note: Mock mode verifies that your provider loads and configures correctly (YAML parsing, model registration, endpoint routing), but returns generic synthetic responses. To validate that response field extraction works with your provider's actual API, test against the real API.


Schema Reference

Complete reference for all provider YAML fields.

Top-Level Structure

config_version: integer   # Optional: Bump when changing (missing = 0)

provider:           # Required: Provider metadata
  id: string
  name: string
  description: string
  env_vars: [string]
  base_url: string          # Optional
  api_key_url: string       # Optional
  website_url: string       # Optional
  docs_url: string          # Optional
  upload:                   # Optional: File upload configuration (nested under provider)

text_to_image:      # Optional: Text-to-image model list
  - id: string

image_to_3d:        # Optional: Image-to-3D model list
  - id: string

Model Fields

text_to_image:     # or image_to_3d
  - id: string           # Unique model ID within provider
    name: string         # Display name
    description: string  # Model description
    endpoint: string     # API endpoint (relative to base_url or absolute)
    method: string       # HTTP method (default: POST)
    request:
      headers: {}        # HTTP headers with ${VAR} interpolation
      body: {}           # JSON body with ${prompt} or ${image_url}
    response:
      response_type: string   # Json, Binary, Base64, or polling
      field: string            # JSONPath for Json/Base64
      polling:                 # Required for polling type
        status_field: string
        status_check_field: string
        success_value: string
        failure_value: string
        result_field: string
        interval_ms: integer
        max_attempts: integer

Variable Interpolation

  • ${prompt} -- User's text prompt
  • ${image_url} -- Auto-generated public URL for uploaded image
  • ${ENV_VAR} -- Any environment variable listed in env_vars

Complete Example

config_version: 1

provider:
  id: "fal.ai"
  name: "fal.ai"
  description: "Fast, serverless AI model API"
  env_vars: ["FAL_KEY"]
  base_url: "https://queue.fal.run"
  api_key_url: "https://fal.ai/dashboard/keys"
  upload:
    endpoint: "https://rest.alpha.fal.ai/storage/upload/initiate?storage_type=fal-cdn-v3"
    method: POST
    request:
      type: initiate_then_put
      headers:
        Authorization: "Key ${FAL_KEY}"
        Content-Type: "application/json"
      initiate_body:
        file_name: "image.png"
        content_type: "image/png"
    response:
      upload_url_field: "upload_url"
      file_url_field: "file_url"

text_to_image:
  - id: "nano-banana-2"
    name: "Nano Banana 2"
    description: "Gemini 3.1 Flash Image -- reasoning-guided generation"
    endpoint: "/fal-ai/nano-banana-2"
    method: POST
    request:
      headers:
        Authorization: "Key ${FAL_KEY}"
        Content-Type: "application/json"
      body:
        prompt: "${prompt}"
        resolution: "1K"
        num_images: 1
    response:
      response_type: polling
      polling:
        status_field: "status_url"
        status_check_field: "status"
        success_value: "COMPLETED"
        failure_value: "FAILED"
        response_url_field: "response_url"
        response_envelope_field: "response"
        result_field: "images[0].url"
        interval_ms: 1000
        max_attempts: 120

image_to_3d:
  - id: "trellis-2"
    name: "Trellis 2"
    description: "High quality 3D model generation"
    endpoint: "/fal-ai/trellis-2"
    method: POST
    request:
      headers:
        Authorization: "Key ${FAL_KEY}"
        Content-Type: "application/json"
      body:
        image_url: "${image_url}"
    response:
      response_type: polling
      polling:
        status_field: "status_url"
        status_check_field: "status"
        success_value: "COMPLETED"
        failure_value: "FAILED"
        response_url_field: "response_url"
        response_envelope_field: "response"
        result_field: "model_glb.url"
        interval_ms: 2000
        max_attempts: 300

Best Practices

  • Always use HTTPS for all URLs
  • Never hardcode API keys -- use ${ENV_VAR} syntax
  • Verify JSONPath expressions against actual API responses
  • Use reasonable polling intervals to respect rate limits
  • Set adequate max_attempts based on typical operation time
  • Test in mock mode first to verify config loads, then test with real API to validate response parsing

← CLI Usage Bundle Structure →