The Future of API Integration

Giulio Alessandrini, Wolfram Research

(RowDefault[, (Spacer1), , (Spacer1), ])  #WolframTechConf

ABSTRACT

This talk introduces the significant enhancements in the upcoming redesign of the ServiceConnections framework. Discover a streamlined process for creating new API connections, with features such as automatic request generation and response parsing, automatic parameter completion and verification, and versatile authentication methodologies. Join us for a technical deep dive into the next wave of API integration.

OUTLINE

Understanding APIs

What is an API?

Why are APIs Useful?

Diving Deep into API Details

API Types

API Characteristics

A Practical Example: Defining Custom APIs in the Wolfram Language

Understanding the Service Connection Framework

Introduction

Current Status and Pain Points

The Future: Framework Redesign

Clear Top Level Access Points

Simplified Authentication Process

Easier Extension

What is an API?

An API, or Application Programming Interface, is a set of rules and protocols that allows different software entities to communicate with each other. It defines the methods and structures developers can use to interact with the software component, be it operating systems, libraries, or other services.

Row[MapThread[Labeled[Show[#,ImageSize->#2,ImageMargins->10],Style[#3,"Text"]]&,{,{120,50,120,50,120},{"user","request/\nresponse","API","???","system"}}],Spacer[20]]

Imagine a waiter in a restaurant. You (the user) provide your order (a request) to the waiter (API), who then brings your food (data) from the kitchen (the system). The API, like the waiter, knows how to get what you want and deliver it to you without you needing to know the intricacies of the kitchen.

Why are APIs Useful?

Modularity and Integration

Diverse applications and systems can work together. E.g., on a mobile phone allow the hardware to interface with software applications.

Efficiency

Developers can leverage existing APIs to build upon functionalities instead of creating from scratch.

Automation

Routine tasks can be automated, as systems can communicate directly without constant human intervention.

Expansion of Services

Allow third parties to create applications or services that are integrated with the company's core services, expanding the reach.

Why are APIs Useful?

Security

Control access to backend systems and data. By exposing only specific, intended functionalities, developers can keep other parts of the system secure and hidden from the outside world.

Scalability

Systems that can grow without a significant rework. New or updated functionalities can be added via new API endpoints without affecting existing operations.

Economic Value

APIs can be monetized. Companies can charge for access or limit the number of free API calls, turning their data or service into a revenue stream.

Real-world Examples

Weather Apps

When you check a weather app, it uses an API to request data from a remote server. The server responds with the data, and the app then presents it to you in a readable format.

Social Media Sharing

When you share a blog post or an article directly to your social media account, it's an API at work. The website communicates with the social platform to post content on your behalf.

Location-based Services

Apps like Uber or DoorDash use APIs to access map and GPS data. When you book a ride or order food, the app communicates in real-time with mapping APIs (like Google Maps) to track the driver's location, estimate time of arrival, and navigate the best route.

A Practical  Example: Defining Custom APIs in the Wolfram Language

Define an API function to get the a country population

f=APIFunction[
{"country" -> "Country"},
EntityValue[#country,EntityProperty["Country","Population"]] &
];

Deploy the API

obj=CloudDeploy[f,"PopulationAPI/population"]

URLExecute[obj,{"country"->"Italy"}]

Add an optional date parameter to query past data

obj=CloudDeploy[APIFunction[
{"country" -> "Country", "year" -> "Integer" :> DateObject[]["Year"]},
EntityValue[#country,EntityProperty["Country","Population",{"Date"->DateObject[{#year}]}]] &
],"PopulationAPI/population"]

URLExecute[obj,{"country"->"Italy","year"->1970}]

A Practical  Example: Defining Custom APIs in the Wolfram Language

This API only has one endpoint:

/population

And two parameters:

country

year

Imagine we had several endpoints, each with it's own parameters...
How can we keep it organized?

The Service Connection Framework

The Service Connection Framework is a part of the Wolfram Language that enables users to connect to and interact with external services. The goal of the framework is to streamline the process of integrating third-party APIs and services into the Wolfram Language.

The Service Connection Framework

Prebuilt Connections

These connections are designed to interact with external services like Twitter, Facebook, Dropbox, Google Analytics, and many others. Each connection is like a plug-and-play component; users don't need to deal with the underlying API directly.

$Services

The Service Connection Framework

Authentication

To use any service that has access controls, you need to authenticate your request. The framework manages the authentication process on your behalf.

Once authenticated, the credentials can be stored securely in your cloud account.

The Service Connection Framework

Authentication

Open APIs

ServiceConnect["ArXiv"]

The Service Connection Framework

Authentication

API key-based services: manual key specification

ServiceConnect["FederalReserveEconomicData"]

The Service Connection Framework

Authentication

OAuth-based services: browser log-in

The Service Connection Framework

Service Requests

After connecting to a service, the framework provides service-specific requests that correspond to the operations available through that service's API.

requests are usually straightforward to use and are designed to abstract away the complexities of making HTTP requests and parsing responses

they behave like WL function calls, taking arguments as needed and returning results in a WL-friendly format

arXiv=ServiceConnect["ArXiv"]

articles=arXiv["Search",<|"Query"->"Quantum Eraser","MaxItems"->4|>];
articles[All,{"Published","Title"}]//Magnify

Understanding the Service Connection Framework

Data Integration

The key purpose framework is its ability to seamlessly integrate external data into your workflow.

retrieved data is automatically converted into native data structures, such as List, Association, Datasets, etc.

you can immediately focus on analyzing and visualizing the data, rather than on the details of how you retrieve it

fred=ServiceConnect["FederalReserveEconomicData"]

data=fred["SeriesData",<|"ID"->{"UNRATE","BBKMGDP"}|>]

DateListPlot[MovingMedian[#,10]&/@data]

Understanding the Service Connection Framework

Current Pain Points

Documentation

While each connection comes with it's own documentation page, the framework itself is poorly documented

Authentication

There are no clear ways to programmatically authenticate

There are no credential storages other then the Wolfram Cloud

Extensibility

complicated paclet based declaration

a lot of boiler plate code required

The Future: Framework Redesign

Clear top level interface

Symbolic connections: ServiceObject

stateless objects for service definitions and connections

assign custom ID and retrieve easily individual connections

Synchronous requests: ServiceExecute

expanded authentication

Asynchronous requests: ServiceSubmit

expanded to support all interesting handlers ("BodyChunk", "ByteCountDownloaded", …)

Symbolic payloads: ServiceRequest/ServiceResponse

more information about the details of the operation

ServiceExecute[ServiceRequest[]]

The Future: Framework Redesign

Clear authentication flow via SystemCredential

API keys – SystemCredentialData

SystemCredential["MYSERVICE_API_KEY"]

OAuth – SecuredAuthenticationKey

SystemCredential["MYSERVICE_OAUTH"]

The Future: Framework Redesign

Simple to Extend

Built-in Operations Simplify Usage

Automatically handles parameter checks, response retrieval, and error parsing.

Minimize Repetitive Coding

the framework manages function execution; simply input connection details and define the request structure.

The Future: Framework Redesign

Simple to Extend

Define and load a new service connection:

CreateServiceConnectionPaclet[\[LeftAssociation]
"ServiceName"->"CatFactsAPI",
"ServiceURL"->URL["https://catfact.ninja"],
"RawRequests"->\[LeftAssociation]
"RawFact"->{
"URL"->"https://catfact.ninja/fact",
"HTTPSMethod"->"GET"
}\[RightAssociation]
\[RightAssociation],OverwriteTarget->True]

The service is ready to be used:

MemberQ[$Services, "giulioa/CatFactsAPI"]

Create a new connection:

catfacts=ServiceConnect["giulioa/CatFactsAPI"]

Perform a request:

catfacts["RawFact"]

The Future: Framework Redesign

Simpler to Extend

Completely stateless connection definition

DefineServiceConnection[\[LeftAssociation]
"ServiceName"->"CatFactsAPI",
"ServiceURL"->URL["https://catfact.ninja"],
"RawRequests"->\[LeftAssociation]
"RawFact"->{
"URL"->"https://catfact.ninja/fact",
"HTTPSMethod"->"GET"
}\[RightAssociation]
\[RightAssociation]]

A Practical  Example: Loading an API in the LLM tech stack

I have created a service connection to the HuggingFace inference API

Connect to the service

ServiceConnect["HuggingFace",Authentication->{"apikey"->SystemCredential["HUGGINGFACE_API_KEY"]}]

This service can now be registered to our LLM services list

Define the registration parameters and register the service

LLMServices`RegisterService[
LLMServices`Chat,(* virtual endpoint *)
"HuggingFace",(* service name *)
<|
"ServiceConnectionRequest" -> "Chat",
"ResponseProcessing" -> ,
"ModelList" :> {"microsoft/DialoGPT-large"}
|>(* registration parameters *)]

Now all the LLM function can use it!

Specify the new service in the LLMConfiguration

LLMSynthesize["Hello there! How are you doing?",LLMEvaluator->LLMConfiguration["Model"->{"HuggingFace","microsoft/DialoGPT-large"}]]

THANK YOU