Searching Files Attached to Records
Learn how to search for files attached to transactions (purchase orders, invoices, etc.) using the SOAP Advanced Search with file join.
Prerequisites
- NetSuite connector configured with
soapresource enabled - Transaction internal ID
Why Use This Action?
Files attached to transactions via the SOAP attach operation cannot be queried using SuiteQL. The search_transaction_files action uses SOAP Advanced Search with fileJoin to retrieve these attachments.
Basic Usage
from abstra.connectors import run_connection_action
# Search for files attached to a purchase order
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": "670932",
"transactionType": "purchaseOrder"
}
)
# Check results
if result['status'] == 'success':
files = result['data']['files']
print(f"Found {len(files)} attached files")
for file in files:
print(f" - {file['fileName']} (ID: {file['fileId']})")
print(f" Type: {file['fileType']}")
print(f" URL: {file['fileUrl']}")
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
transactionId | string | Yes | Internal ID of the transaction |
transactionType | string | No | Type of transaction (default: purchaseOrder) |
Supported Transaction Types
purchaseOrder- Purchase OrderssalesOrder- Sales Ordersinvoice- InvoicesvendorBill- Vendor Billsestimate- Estimates
Response Format
{
"status": "success",
"data": {
"success": True,
"totalRecords": 1,
"files": [
{
"fileId": "678765",
"fileName": "invoice.pdf",
"fileUrl": "/core/media/media.nl?id=678765&c=...",
"fileType": "_PDF"
}
]
}
}
Practical Examples
Get Files from a Purchase Order
def get_po_attachments(po_internal_id):
"""Get all files attached to a purchase order"""
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": str(po_internal_id),
"transactionType": "purchaseOrder"
}
)
if result['status'] == 'success':
return result['data']['files']
return []
# Usage
files = get_po_attachments("670932")
for f in files:
print(f"{f['fileName']} - {f['fileType']}")
Get Files from an Invoice
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": "123456",
"transactionType": "invoice"
}
)
Download Attached File Content
import base64
# 1. Search for attached files
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": "670932",
"transactionType": "purchaseOrder"
}
)
# 2. Download each file
for file in result['data']['files']:
file_details = run_connection_action(
"netsuite",
"get_file",
{"fileId": file['fileId']}
)
# Save to disk
content = file_details['data'].get('content')
if content:
with open(file['fileName'], 'wb') as f:
f.write(base64.b64decode(content))
print(f"Downloaded: {file['fileName']}")
Check if Transaction Has Attachments
def has_attachments(transaction_id, transaction_type="purchaseOrder"):
"""Check if a transaction has any file attachments"""
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": str(transaction_id),
"transactionType": transaction_type
}
)
if result['status'] == 'success':
return len(result['data']['files']) > 0
return False
# Usage
if has_attachments("670932"):
print("PO has attachments")
else:
print("PO has no attachments")
Process Multiple Transactions
def get_attachments_for_transactions(transaction_ids, transaction_type="purchaseOrder"):
"""Get attachments for multiple transactions"""
all_attachments = {}
for trans_id in transaction_ids:
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": str(trans_id),
"transactionType": transaction_type
}
)
if result['status'] == 'success':
all_attachments[trans_id] = result['data']['files']
return all_attachments
# Usage
po_ids = ["670932", "670933", "670934"]
attachments = get_attachments_for_transactions(po_ids)
for po_id, files in attachments.items():
print(f"PO {po_id}: {len(files)} files")
Building Full File URLs
The fileUrl returned is a relative path. To build the full URL:
def get_full_file_url(account_id, relative_url):
"""Convert relative URL to full NetSuite URL"""
return f"https://{account_id}.app.netsuite.com{relative_url}"
# Example
account_id = "1234567"
file_url = "/core/media/media.nl?id=678765&c=1234567&h=abc123"
full_url = get_full_file_url(account_id, file_url)
print(f"Full URL: {full_url}")
Error Handling
result = run_connection_action(
"netsuite",
"search_transaction_files",
{
"transactionId": "670932",
"transactionType": "purchaseOrder"
}
)
if result['status'] == 'error':
print(f"Error: {result['message']}")
elif result['data']['success']:
files = result['data']['files']
if files:
print(f"Found {len(files)} files")
else:
print("No files attached to this transaction")
else:
print("Search failed")
Troubleshooting
"Action search_transaction_files not found"
- Enable
soapresource in your NetSuite connection configuration
Empty Results
- Verify the transaction ID is correct
- Check that the transaction type matches
- Confirm files were attached (not just referenced)
Permission Errors
- Ensure the NetSuite role has Transaction Search permissions
- Verify the token has access to the transaction type
Comparison: SuiteQL vs SOAP Search
| Feature | SuiteQL (query) | SOAP (search_transaction_files) |
|---|---|---|
| Files via Communication subtab | Yes | Yes |
| Files via SOAP attach | No | Yes |
| Query flexibility | High | Limited to transaction + files |
| Performance | Faster | Slower |
Use search_transaction_files when:
- Files were attached using the SOAP
attachaction - SuiteQL queries return empty for known attachments
Use SuiteQL query when:
- Files were attached via NetSuite UI (Communication subtab)
- You need complex filtering or joins