Use the C3 AI REST API in the C3 Agentic AI Platform
The REST Type can be mixed in to invoke third-party API calls. These Types define the API calls as standard methods on the Type, the same way you would define a function in a standard Type. All methods on a given REST Type can be executed against the same base URL, but specific endpoints can be defined.
Examples of Types that mix REST
Examples of Types that mix REST are Google and Jira.
Using the Google API
Google is an example of a Type that mixes the REST Type. For access, you need to specify the url in a JSON file under the config/rest directory in your package. The auth properties must be stored as a config on the environment.
For more information about package structure, see Package Management Overview. See Access Control to learn about configuring auth properties.
/**
* Google Rest endpoints wrapper
*
* Instance (REST).url: "https://maps.googleapis.com/<instance>"
* Instance (REST).auth: Authenticator.generateBasicAuthToken(GOOGLE_USER, GOOGLE_USER_TOKEN)
*
* Usage:
* // Store config on the environment
* var baseUrl = `base url`;
* var googleConfig = Google.make({name : '<instance>'}).config(true)
* googleConfig.setConfigValue('url', 'https://maps.googleapis.com/<instance>')
* googleConfig.setSecretValue('auth', Authenticator.generateBasicAuthToken('<username>', <TokenValue>))
* // Create a Google instance by referencing the stored config
* var googleConfig = Google.make({name : '<instance>'}).config(true)
* var google = Google.make({name: '<instance>', url: googleConfig.url, auth: googleConfig.auth})
* // call something on this google instance
*/
type Google mixes REST {
/**
* Calls Google's geocode API with the supplied parameters
*/
@rest(uri='maps/api/geocode/json', method='GET')
geocode: abstract function(@rest(queryParameter=true)
address: !string,
components: string,
@rest(queryParameter=true)
client: string): GoogleGeocodeResults
/**
* Calls Google's timezone API with the supplied parameters
*/
@rest(uri='maps/api/timezone/json', method='GET')
timezone: abstract function(@rest(queryParameter=true)
location: !string,
@rest(queryParameter=true)
timestamp: int,
@rest(queryParameter=true)
client: string): GoogleTimeZone
}In the example above, there are two APIs with different endpoints.
- The
geocodefunction Rest endpoint ishttps://<base url>/job/master/4368/maps/api/geocode/json - The
timezonefunction Rest endpoint ishttps://<base url>/job/master/4368/maps/api/timezone/json
Notice how both functions request the same base URL https://<base url>. The base URL is stored in the config file as the key value pair: "url" : "https://<base url>".
The config file name is the same as the Type name in the majority of the cases.
A Google Geocoding API request takes the following form:
https://maps.googleapis.com/maps/api/geocode/outputFormat?parametersThe uri in the @rest annotation indicates the output format is in JSON format.
When defining Types, annotations are used to configure the Types and the fields on them. Annotations are defined on the line above the Type, or the field, to which they apply. Add the annotation @rest(uri='job', method='GET'). The method field in the @rest annotation indicates build is a GET request and requires the /job argument appended to the URL. Supported Http methods are GET, PUT, POST, and HEAD for the respective requests. If you need to include a parameter, add the parameter and surround it with uriPrefix and uriSuffix.
Refer to the topic on annotations for more information about annotations.
In both functions, notice there is a query parameter. Query parameters are a defined set of parameters appended to the end of the URL after the ? symbol. Query parameters are extensions of the URL and used to help define content or actions based on the data being passed.
Replace the field queryParameter=true with partOfURI=true. The ! in front of string in the address parameter of the geocode function indicates the field is required and the value must be a string.
Using the Jira API
Unlike the Google Type, the Jira Type mixes multiple Types including the REST Type.
Unlike the previous example that contained a GET Http request, this example is a PUT request. You need to add data to the submit request. That is why the second parameter fields does not have the @rest(partofURI=true) annotation. The data you want to send over is not part of the REST endpoint.
type Jira mixes REST, JiraSoftwareMethods, DefaultInstance<Jira> {
/**
* Edit a Jira ticket
* You can NOT edit Status, Projects, and Comments with this method
* To edit the status of the issue, use transition function below.
* To add comments, use comment function below
*
* @param issueIdOrKey
* ID or key of the issue you want to edit. ID is a unique number.
* @param fields
* JiraIssueFields we want to edit
*/
@rest(uri='issue', method='PUT')
edit: abstract function(@rest(partOfURI=true, uriPrefix='/') issueIdOrKey: !string, fields: !JiraIssueFields)
}The REST Type handles calling the third-party APIs for you. You do not need to create and implement the function. Adding the keyword abstract in front of the function indicates this Type has additional custom methods that are not REST endpoints. For example, if you want to create a separate helper function to do some additional calculations or filtering but Jira does not provide this support.
Examples of Applications using REST types
The applications using REST Types should have the following structure (truncated for simplicity):
.
├── <package name>.c3pkg.json
├── rest
│└── config
│ ├── typeName/instanceName.json
└── src
└── packageName
├── typeName.c3typ
└── typeName.jsBelow are some examples of the config files and what they include:
Google JSON output
{
"url": "https://maps.googleapis.com/",
"retries": 3,
"maxConn": 1000,
"timeout": 3000
}Twilio JSON output
{
"retries": 3,
"maxConn": 1000,
"timeout": 300
}