Search Client
This page describes the Search API for indexing and searching provenance claims and accounts through Royal’s infrastructure. For authentication details, please refer to the Authentication page, and for overall API best practices, see API Guidelines.
Overview
The Search API enables you to:
- Search for provenance claims by content hash, name, or other metadata
- Search for accounts by username or ID
- Perform combined searches across multiple entity types
- Paginate through search results
Prerequisites
Before you can use the Search API, you need to:
- Follow the Authentication guide to authenticate your requests.
- Follow the API Guidelines for all REST API requests.
- Review the SearchClient implementation for detailed class usage.
Quick Start
- Install the required dependency:
npm install typesense --save-dev
-
Copy the SearchClient to your project.
-
Create a client instance and perform a basic search:
const API_KEY = "ryl_sk_YOUR_SECRET_KEY";const client = new SearchClient({ apiKey: API_KEY });
// Search across all entity typesconst searchResult = await client.searchAll("Alice");
// Search just for accountsconst accountResults = await client.searchAccounts("Alice");
// Search just for provenance claimsconst claimResults = await client.searchClaims("Artwork");
Client Configuration
Class: SearchClient
The SearchClient
provides an interface for searching provenance claims and accounts. For the complete implementation, see the search client source code.
Constructor
constructor(host: string, apiKey?: string, rawResponses = false)
Parameter | Type | Required | Description |
---|---|---|---|
host | string | Yes | The base URL for the Royal API (e.g., “https://api.royal.io 🔗”) |
apiKey | string | Yes | Your Royal API key for authentication |
rawResponses | boolean | No | Whether to return raw API responses (default: false) |
API Methods
Search All Entities
searchAll(q = '', page = 1, perPage = 10)
Searches across all entity types (accounts and provenance claims).
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
q | string | No | The search query term |
page | number | No | Page number for pagination (default: 1) |
perPage | number | No | Results per page (default: 10) |
Response
Returns a PerformSearchResponse
containing matching accounts and provenance claims.
Search Accounts
searchAccounts(q = '', page = 1, perPage = 10)
Searches only for accounts.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
q | string | No | The search query term |
page | number | No | Page number for pagination (default: 1) |
perPage | number | No | Results per page (default: 10) |
Response
Returns a PerformSearchResponse
containing matching account records.
Search Provenance Claims
searchClaims(q = '', page = 1, perPage = 10)
Searches only for provenance claims.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
q | string | No | The search query term |
page | number | No | Page number for pagination (default: 1) |
perPage | number | No | Results per page (default: 10) |
Response
Returns a PerformSearchResponse
containing matching provenance claim records.
Advanced Use Cases
Advanced Search
performSearch<T>(searchParameters, options = {})
Performs a customized search with full control over search parameters.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
searchParameters | SearchParams or SearchParamsWithPreset | Yes | Typesense search parameters |
options | SearchOptions | No | Additional search options |
Response
Returns a PerformSearchResponse<T>
containing the search results.
Best Practices
While you can use the performSearch
method directly with search parameters from the Typesense documentation 🔗, we strongly recommend creating specific search functions within your application by extending the class or following the pattern of the built-in methods.
This approach improves code readability, maintainability, and reusability. Here are examples of custom search functions you might implement:
Example: Search for User Claims on a Specific Registrar
public async searchUserClaimsOnRegistrar(ORIGINATOR_ID: number | string | bigint, page = 1) { const params = { q: "*", query_by: "originatorId,registrarId", filter_by: `type:provenanceClaim && originatorId:${ORIGINATOR_ID} && registrarId:${YOUR_APP_REGISTRAR_ID}`, sort_by: "psqlId:desc", };
return this.performSearch<ProvenanceClaimDocumentType>(params);}
Example: Search by Content Hash
public async searchByContentHash(contentHash: string) { const params = { q: contentHash.toLowerCase(), query_by: "contentHash", filter_by: `type:provenanceClaim`, };
return this.performSearch<ProvenanceClaimDocumentType>(params);}
Proxying Client-Side Calls
When building client-side applications, it’s best practice to avoid exposing your API keys directly in browser code. You can create a server-side proxy endpoint to handle search requests securely.
Server Implementation
Create a server endpoint to proxy search requests:
import { SearchClient } from '@royal/protocol-client';import { NextRequest } from 'next/server';
/** * Since this code would be running on the server, you can * use your Secret Key without any issues */const API_KEY = "ryl_sk_YOUR_SECRET_KEY";const client = new SearchClient({ apiKey: API_KEY });
export async function POST(request: NextRequest) { const data = (await request.json()) as { searchParameters: SearchParams | SearchParamsWithPreset; options: SearchOptions; };
const result = await client.performSearch( data.searchParameters, data.options, );
return Response.json(result, { status: 200 });}
Client Implementation
Configure the client to use your internal API endpoint:
import { SearchClient } from '@royal/protocol-client';import { useState } from 'react';
/** * This code would run on the client side, and we don't * want to expose the API key, so we create the client * and set the host to our internal endpoint to proxy the * calls. * * We also set the `rawResponses` attribute to true because * the server-side client is already parsing the responses */const client = new SearchClient({ host: "https://mysiteurl/api/search", rawResponses: true});
export const MyClientSidePage = () => { const [results, setResults] = useState([]);
const search = async (query: string) => { const { data } = await client.searchAll(query); setResults(data); }
return ( <> <input onChange={(evt) => search(evt.target.value)} /> <ul> {results.map((item) => ( <li key={item.id}>Claim {item.psqlId}</li> ))} </ul> </> );}
This pattern ensures your API key remains secure on your server while still allowing client-side applications to perform searches through your proxy endpoint.
Response Types
PerformSearchResponse
type PerformSearchResponse<T> = { data: T[]; // Array of matching documents total: number; // Total number of matching results numPages: number; // Total number of pages};
AccountDocumentType
type AccountDocumentType = { type: "account"; id: string; psqlId: string; username: string; custody: string; provenanceClaimCount: number; originatedProvenanceClaimCount: number; registeredProvenanceClaimCount: number; dayBucket: number; hourBucket: number; recovery: string; createdAt: string; updatedAt: string;};
ProvenanceClaimDocumentType
type ProvenanceClaimDocumentType = { type: 'provenanceClaim'; id: string; psqlId: string; originatorAddress: string; originatorId: string; originatorUsername: string; registrarAddress: string; registrarId: string; registrarUsername: string; blockNumber: string; contentHash: string; transactionHash: string; transactionIndex: number; nftContract?: string; nftTokenId?: string; dayBucket: number; hourBucket: number; metadata?: Record<string, any> & { name?: string; description?: string; image?: string; animation_url?: string; external_url?: string; attributes?: Array<any>; royal?: { provenance?: { attributes?: Array<any>; content_hash?: string; file_locations?: Array<{ url: string; }>; title?: string; }; }; }; createdAt: string; updatedAt: string;};
Error Handling
When a search fails, the client will return a response with empty data:
{ data: [], total: 0, numPages: 0}
Additional Information
For complete API integration tips, please refer to the API Guidelines. To examine the full implementation of the search client, see the SearchClient class.
Note: This documentation covers only the Search API for querying provenance claims and accounts. For information about registering new claims, please see the Registration section.