Working with Assets

This guide covers how to work with assets in the Athena SDK, including listing assets, retrieving asset details, and understanding the tags structure.

Understanding the Tags Structure

Every asset in Athena has a tags object that contains both system-managed fields and custom tags. This is important because the asset ID is stored in tags.asset_id as an array of strings.

System Fields in Tags

The tags object contains the following system-managed fields:

FieldTypeDescription
asset_idstring[]Array containing the unique asset identifier. This is the primary way to get the asset ID.
titlestring[]Array containing the asset title
media_typestring[]Array containing the MIME type or Athena-specific media type
athena_original_typestring[]Array containing the original asset type
athena_converted_typestring[]Array containing the converted asset type
workspace_visiblestring[]Array containing visibility setting ("true" or "false")
shared_with_user_idsstring[]Array of user IDs who have access to this asset
custom_tagsstring[]Array of user-defined custom tags for categorization

Example Tags Object

1{
2 "tags": {
3 "asset_id": ["asset_92492920-d118-42d3-95b4-00eccfe0754f"],
4 "title": ["Quarterly Report Q1 2024"],
5 "media_type": ["application/pdf"],
6 "athena_original_type": ["document"],
7 "athena_converted_type": ["pdf"],
8 "workspace_visible": ["true"],
9 "shared_with_user_ids": ["user_123", "user_456"],
10 "custom_tags": ["finance", "quarterly-report"]
11 }
12}
1

Install Package

$pnpm add @athenaintel/sdk
2

Set Up Client

1import { AthenaIntelligenceClient } from '@athenaintel/sdk';
2
3const client = new AthenaIntelligenceClient({
4 apiKey: process.env.ATHENA_API_KEY,
5});
3

List Assets

Retrieve a paginated list of assets with optional filtering:

1// List all assets (paginated)
2const assets = await client.assets.list({
3 limit: 50,
4 offset: 0,
5});
6
7console.log(`Total assets: ${assets.total}`);
8console.log(`Has more: ${assets.has_more}`);
9
10// Process each asset
11for (const asset of assets.items) {
12 // Extract the asset ID from tags
13 const assetId = asset.tags?.asset_id?.[0];
14 console.log(`Asset: ${asset.title} (ID: ${assetId})`);
15}
4

Filter Assets by Type

Use filters to find specific types of assets:

1// Find all folders
2const folders = await client.assets.list({
3 limit: 50,
4 filters: JSON.stringify({
5 media_type: 'athena/folder',
6 }),
7});
8
9// Find all PDF documents
10const pdfs = await client.assets.list({
11 limit: 50,
12 filters: JSON.stringify({
13 media_type: 'application/pdf',
14 }),
15});
16
17// Find assets with specific custom tags
18const taggedAssets = await client.assets.list({
19 limit: 50,
20 filters: JSON.stringify({
21 tags: {
22 custom_tags: ['finance'],
23 },
24 }),
25});
5

Get Asset by ID

Retrieve a single asset with full metadata:

1const assetId = 'asset_92492920-d118-42d3-95b4-00eccfe0754f';
2const asset = await client.assets.get(assetId);
3
4console.log('Asset details:');
5console.log(` Title: ${asset.title}`);
6console.log(` Media Type: ${asset.media_type}`);
7console.log(` Created: ${asset.created_at}`);
8console.log(` Summary Ready: ${asset.summary_ready}`);
9
10// Access the asset ID from tags
11const retrievedAssetId = asset.tags?.asset_id?.[0];
12console.log(` Asset ID (from tags): ${retrievedAssetId}`);
13
14// Access custom tags
15const customTags = asset.tags?.custom_tags || [];
16console.log(` Custom Tags: ${customTags.join(', ')}`);
6

Search for Folders

A common operation is searching for folders to organize assets:

1async function findFolderByName(folderName: string) {
2 const folders = await client.assets.list({
3 limit: 100,
4 filters: JSON.stringify({
5 media_type: 'athena/folder',
6 title_substring: folderName,
7 }),
8 });
9
10 if (folders.items.length === 0) {
11 console.log(`No folder found with name containing: ${folderName}`);
12 return null;
13 }
14
15 const folder = folders.items[0];
16 const folderId = folder.tags?.asset_id?.[0];
17
18 console.log(`Found folder: ${folder.title}`);
19 console.log(`Folder ID: ${folderId}`);
20
21 return folderId;
22}
23
24// Usage
25const folderId = await findFolderByName('Reports');
7

Extract Asset ID Helper

Create a helper function to safely extract the asset ID:

1function getAssetId(asset: { tags?: { asset_id?: string[] } }): string | undefined {
2 return asset.tags?.asset_id?.[0];
3}
4
5// Usage
6const assets = await client.assets.list({ limit: 10 });
7for (const asset of assets.items) {
8 const id = getAssetId(asset);
9 if (id) {
10 console.log(`Processing asset: ${id}`);
11 }
12}
8

Complete Example

Here’s a complete working example that demonstrates listing and filtering assets:

1import { AthenaIntelligenceClient, AthenaIntelligenceError } from '@athenaintel/sdk';
2
3async function workWithAssets() {
4 try {
5 const client = new AthenaIntelligenceClient({
6 apiKey: process.env.ATHENA_API_KEY,
7 });
8
9 // List recent assets
10 console.log('Listing recent assets...');
11 const assets = await client.assets.list({
12 limit: 10,
13 sort: JSON.stringify([
14 { field: 'updated_at', direction: 'desc' },
15 ]),
16 });
17
18 console.log(`Found ${assets.total} total assets`);
19
20 for (const asset of assets.items) {
21 const assetId = asset.tags?.asset_id?.[0];
22 const customTags = asset.tags?.custom_tags || [];
23
24 console.log(`\nAsset: ${asset.title}`);
25 console.log(` ID: ${assetId}`);
26 console.log(` Type: ${asset.athena_original_type}`);
27 console.log(` Media Type: ${asset.media_type}`);
28 console.log(` Custom Tags: ${customTags.length > 0 ? customTags.join(', ') : 'none'}`);
29 console.log(` Summary Ready: ${asset.summary_ready}`);
30 }
31
32 // Find all folders
33 console.log('\n\nSearching for folders...');
34 const folders = await client.assets.list({
35 limit: 50,
36 filters: JSON.stringify({
37 media_type: 'athena/folder',
38 }),
39 });
40
41 console.log(`Found ${folders.total} folders`);
42 for (const folder of folders.items) {
43 const folderId = folder.tags?.asset_id?.[0];
44 console.log(` - ${folder.title} (${folderId})`);
45 }
46
47 } catch (error) {
48 if (error instanceof AthenaIntelligenceError) {
49 console.error(`Athena API error (${error.statusCode}): ${error.message}`);
50 } else {
51 console.error('Unexpected error:', error);
52 }
53 }
54}
55
56workWithAssets();

Response Structure

PublicAssetOut

When you retrieve an asset, you receive a PublicAssetOut object with the following structure:

1interface PublicAssetOut {
2 // Required fields
3 created_by_id: string;
4 created_at: string; // ISO 8601 format
5 title: string;
6 updated_at: string; // ISO 8601 format
7 is_archived: boolean;
8 is_hidden: boolean;
9 media_type: string;
10 athena_converted_type: string;
11 athena_original_type: string;
12 summary_ready: boolean;
13
14 // Optional fields
15 created_by_email?: string;
16 tags?: {
17 asset_id?: string[];
18 title?: string[];
19 media_type?: string[];
20 athena_original_type?: string[];
21 athena_converted_type?: string[];
22 workspace_visible?: string[];
23 shared_with_user_ids?: string[];
24 custom_tags?: string[];
25 };
26 athena_metadata?: Record<string, unknown>;
27 summary?: string;
28 summary_status?: string;
29}

PaginatedAssetsOut

When listing assets, you receive a PaginatedAssetsOut object:

1interface PaginatedAssetsOut {
2 total: number; // Total number of assets matching the query
3 limit: number; // Maximum number of assets in this response
4 offset: number; // Number of assets skipped
5 has_more: boolean; // Whether there are more assets available
6 next_offset?: number; // Offset for the next page (null if no more pages)
7 items: PublicAssetOut[]; // Array of assets
8}