Skip to main content
This guide covers how to create dashboards for your tenants using the Papermap Dashboard API.

Prerequisites

Before implementing, ensure you have:
  • Papermap API credentials (API Key ID and Secret Key)
  • Your workspace ID
  • API endpoint URL (obtain from your Papermap dashboard settings)
  • HMAC authentication implemented (see Authentication)

Database Model

First, you should have created a table in your database to store the mapping between your tenant and the dashboard ID. See the Database Model section in Backend Implementation for details. Purpose: Links your tenant to a Papermap dashboard ID for secure access and isolation.

Creating a Dashboard

The base URL for the Papermap API is https://prod.dataapi.papermap.ai/.
The get_auth_headers function is a helper function that generates the HMAC signature for the API request found in the HMAC Authentication
Create a dashboard via the Papermap API for each tenant:
import httpx

async def create_dashboard(
    tenant_id: str,
    workspace_id: str,
    name: str,
    description: Optional[str] = None,
    created_by: Optional[str] = None
):
    # 1. Call Papermap API with HMAC signature
    headers = _get_auth_headers(workspace_id, API_KEY_ID, SECRET_KEY)

    payload = {
        "workspace_id": workspace_id,
        "title": name,
        "description": description
    }

    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{PAPERMAP_API_URL}/api/v1/external/dashboards",
            headers=headers,
            json=payload
        )

    external_dashboard = response.json()
    dashboard_id = external_dashboard["data"]["data"]["dashboard_id"]

    # 2. Store mapping in your database
    tenant_dashboard = TenantDashboard.create(
        session=db,
        tenant_id=tenant_id,
        workspace_id=workspace_id,
        dashboard_id=dashboard_id,
        created_by=created_by
    )

    return tenant_dashboard

Workflow Diagram

1. Client Request → POST /api/v1/dashboards
   {
     "tenant_id": "org-123",
     "workspace_id": "workspace-456",
     "name": "Sales Dashboard"
   }

2. Your API → Generate HMAC Signature
   payload = "workspace-456" + "1699999999"
   signature = HMAC-SHA256(payload, secret_key)

3. Your API → Call Papermap Dashboard API
   POST ${PAPERMAP_API_URL}/api/v1/external/dashboards
   Headers:
     X-API-Key-ID: your-api-key
     X-Workspace-ID: workspace-456
     X-Valid-Until: 1699999999
     X-Signature: abc123...

4. Papermap API → Returns Dashboard
   {data:... {data: {dashboard_id: "dashboard-789", ...}}}

5. Your API → Store Mapping in Database
   TenantDashboard:
     tenant_id: org-123
     workspace_id: workspace-456
     dashboard_id: dashboard-789

6. Return to Client
   { "success": true, "data": {...} }

Key Considerations

Tenant Isolation

Each tenant should have their own dashboard:
  • One dashboard per tenant ensures data isolation
  • Store the tenant-to-dashboard mapping in your database
  • Verify tenant ownership before allowing access

Dashboard Naming

Use clear, consistent naming conventions:
  • Include tenant identifier in dashboard name
  • Example: "Dashboard - Acme Corp" or "Acme Corp Analytics"
  • Makes management easier in the Papermap admin panel

Error Handling

Handle common errors gracefully:
try:
    dashboard = await create_dashboard(tenant_id, workspace_id, name)
except httpx.HTTPStatusError as e:
    if e.response.status_code == 401:
        # Invalid credentials or expired signature
        raise Exception("Authentication failed")
    elif e.response.status_code == 409:
        # Dashboard already exists
        raise Exception("Dashboard already exists for this tenant")
    else:
        # Other errors
        raise Exception(f"Failed to create dashboard: {e}")

Next Steps