This document describes the Jules API integration used in this mobile client.
https://jules.googleapis.com/v1alpha
All requests require the X-Goog-Api-Key header:
X-Goog-Api-Key: AIzaSy...GET /sessions?pageSize=20Response:
{
"sessions": [
{
"name": "sessions/abc123",
"title": "Fix bug in auth module",
"state": "ACTIVE",
"createTime": "2024-01-15T10:30:00Z",
"updateTime": "2024-01-15T10:35:00Z"
}
],
"nextPageToken": "..."
}Session States:
| State | Description | App Display (ja/en) |
|---|---|---|
STATE_UNSPECIFIED |
Unknown/Creating state | 作成中 / Creating |
ACTIVE |
Session is in progress | 処理中 / Processing |
COMPLETED |
Session finished successfully | 完了 / Completed |
FAILED |
Session encountered an error | 失敗 / Failed |
POST /sessions
Content-Type: application/json
{
"prompt": "Fix the login bug",
"sourceContext": {
"source": "sources/github/owner/repo",
"githubRepoContext": {
"startingBranch": "main"
}
},
"title": "Fix the login bug..."
}Response:
{
"name": "sessions/new123",
"title": "Fix the login bug...",
"state": "ACTIVE",
"createTime": "2024-01-15T10:30:00Z",
"updateTime": "2024-01-15T10:30:00Z"
}GET /sources?pageSize=20&pageToken=...Response:
{
"sources": [
{
"name": "sources/github/owner/repo",
"displayName": "My Repository",
"githubRepo": {
"owner": "owner",
"repo": "repo",
"isPrivate": false,
"defaultBranch": {
"displayName": "main"
}
}
}
],
"nextPageToken": "..."
}GET /sessions/{sessionId}/activities?pageSize=50Response:
{
"activities": [
{
"name": "sessions/abc/activities/1",
"id": "1",
"createTime": "2024-01-15T10:30:00Z",
"originator": "agent",
"agentMessaged": {
"agentMessage": "I'll analyze the codebase..."
}
},
{
"name": "sessions/abc/activities/2",
"id": "2",
"createTime": "2024-01-15T10:31:00Z",
"originator": "agent",
"planGenerated": {
"plan": {
"id": "plan123",
"steps": [
{
"id": "step1",
"title": "Analyze authentication module",
"description": "Review current auth implementation"
}
]
}
}
}
],
"nextPageToken": "..."
}Activity Types:
| Type | Field | Description |
|---|---|---|
| Agent Message | agentMessaged.agentMessage |
Text message from Jules |
| User Message | userMessaged.userMessage |
Text message from user |
| Plan Generated | planGenerated.plan |
AI-generated task plan |
| Plan Approval Request | planApprovalRequested.planId |
Waiting for user approval |
| Plan Approved | planApproved.planId |
User approved the plan |
| Progress Update | progressUpdated.title/description |
Task progress info |
| Artifacts | artifacts[] |
Bash output, code changes, etc. |
POST /{planId}:approveResponse:
{}Error Response Format:
{
"error": {
"code": 400,
"message": "Invalid request",
"status": "INVALID_ARGUMENT"
}
}Common Error Codes:
| Code | Status | Description |
|---|---|---|
| 400 | INVALID_ARGUMENT |
Bad request parameters |
| 401 | UNAUTHENTICATED |
Missing or invalid API key |
| 403 | PERMISSION_DENIED |
Access denied |
| 404 | NOT_FOUND |
Resource not found |
| 429 | RESOURCE_EXHAUSTED |
Rate limit exceeded |
| 500 | INTERNAL |
Server error |
// API Error
interface ApiError {
error: {
code: number;
message: string;
status: string;
};
}
// Source
interface Source {
name: string;
displayName?: string;
githubRepo?: {
owner: string;
repo: string;
isPrivate?: boolean;
defaultBranch?: {
displayName: string;
};
};
}
// Session
interface Session {
name: string;
title?: string;
state: "STATE_UNSPECIFIED" | "ACTIVE" | "COMPLETED" | "FAILED";
createTime: string;
updateTime: string;
}
// Activity
interface Activity {
name: string;
id: string;
createTime: string;
originator: "agent" | "user";
agentMessaged?: { agentMessage: string };
userMessaged?: { userMessage: string };
progressUpdated?: { title?: string; description?: string };
planGenerated?: { plan: Plan };
planApproved?: { planId: string };
planApprovalRequested?: { planId: string };
artifacts?: Artifact[];
}
// Plan
interface Plan {
id: string;
steps?: PlanStep[];
}
interface PlanStep {
id?: string;
title: string;
description?: string;
state?: string;
index?: number;
}
// Artifact
interface Artifact {
bashOutput?: {
command: string;
output?: string;
exitCode?: number;
};
changeSet?: {
source: string;
gitPatch?: {
unidiffPatch: string;
baseCommitId?: string;
};
};
}The API may apply rate limiting. If you receive a 429 error, implement exponential backoff:
async function fetchWithRetry(url: string, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url);
} catch (err) {
if (err.status === 429 && i < retries - 1) {
await sleep(Math.pow(2, i) * 1000);
continue;
}
throw err;
}
}
}For real-time updates, the app polls the activities endpoint:
// Poll every 5 seconds
const interval = setInterval(async () => {
const activities = await fetchActivities(sessionId, true); // silent
if (activities.length > prevLength) {
setActivities(activities);
}
}, 5000);The app integrates with GitHub's REST API for repository management, webhooks, and workflow monitoring.
https://api.github.com
GitHub API requests use personal access tokens:
Authorization: Bearer ghp_...GET /user/repos - List user repositories
GET /repos/{owner}/{repo} - Get repository details
GET /repos/{owner}/{repo}/actions/workflows - List workflows
GET /repos/{owner}/{repo}/actions/runs - List workflow runs
GET /repos/{owner}/{repo}/pulls - List pull requestsPOST /repos/{owner}/{repo}/hooks - Create webhook
GET /repos/{owner}/{repo}/hooks - List webhooks
DELETE /repos/{owner}/{repo}/hooks/{hook_id} - Delete webhookGitHub API has stricter rate limits than Jules API:
- Authenticated requests: 5,000 per hour
- Unauthenticated requests: 60 per hour
The app implements intelligent caching and background sync to minimize API calls.
GitHub API errors follow standard HTTP status codes with detailed error messages:
{
"message": "Not Found",
"documentation_url": "https://docs.github.com/rest"
}Webhooks are secured with HMAC-SHA256 signatures:
const signature = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
const expectedSignature = `sha256=${signature}`;