or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-operations.mdgoogle-directory-apis.mdindex.mdmain-connector.md

google-directory-apis.mddocs/

0

# Google Directory APIs

1

2

Direct access to Google Directory API resources with authentication, pagination, error handling, and retry logic. These classes provide low-level access to users, groups, and group membership data from Google Workspace.

3

4

## Capabilities

5

6

### Core API Wrapper

7

8

The main API class that handles Google Directory API authentication and request execution.

9

10

```python { .api }

11

class API:

12

"""

13

Core Google Directory API client with authentication handling.

14

15

Manages OAuth 2.0 and Service Account authentication, constructs

16

Google API service resources, and executes API requests with

17

automatic retry and rate limiting.

18

"""

19

20

def __init__(self, credentials: Mapping[str, Any]):

21

"""

22

Initialize the Google Directory API client.

23

24

Parameters:

25

- credentials: Dict containing authentication credentials

26

For OAuth: client_id, client_secret, refresh_token

27

For Service Account: credentials_json, email

28

"""

29

30

def get(self, name: str, params: Dict = None) -> Dict:

31

"""

32

Execute Google Directory API GET request with retry logic.

33

34

Parameters:

35

- name: API resource name ('users', 'groups', 'members')

36

- params: Dict of query parameters for the API request

37

38

Returns:

39

- Dict: API response containing requested data

40

41

Features automatic retry with exponential backoff for rate limits

42

and quota exceeded errors using the backoff decorator.

43

"""

44

45

@staticmethod

46

def _load_account_info(credentials_json: str) -> Dict:

47

"""

48

Parse service account credentials from JSON string.

49

50

Parameters:

51

- credentials_json: JSON string containing service account info

52

53

Returns:

54

- Dict: Parsed account information

55

"""

56

57

def _obtain_service_account_creds(self):

58

"""

59

Obtain Google service account credentials for domain-wide delegation.

60

61

Uses the credentials_json and email from the configuration to create

62

service account credentials with the required Directory API scopes

63

and subject delegation for the admin email.

64

"""

65

66

def _obtain_web_app_creds(self):

67

"""

68

Obtain Google OAuth 2.0 web application credentials.

69

70

Uses client_id, client_secret, and refresh_token from configuration

71

to create OAuth credentials. Automatically refreshes tokens if expired.

72

"""

73

74

def _obtain_creds(self):

75

"""

76

Determine credential type and obtain appropriate authentication.

77

78

Automatically detects whether to use service account or OAuth

79

credentials based on the presence of credentials_json or client_id

80

in the configuration.

81

"""

82

83

def _construct_resource(self):

84

"""

85

Construct the Google Directory API service resource.

86

87

Obtains credentials if not already available and builds the

88

'admin' service with 'directory_v1' API version.

89

"""

90

91

def _get_resource(self, name: str):

92

"""

93

Get Google Directory API resource by name.

94

95

Parameters:

96

- name: Resource name ('users', 'groups', 'members')

97

98

Returns:

99

- Google API resource object for the specified resource type

100

"""

101

```

102

103

### Stream API Base Class

104

105

Abstract base class providing common functionality for all Google Directory stream APIs.

106

107

```python { .api }

108

class StreamAPI(ABC):

109

"""

110

Abstract base class for Google Directory stream APIs.

111

112

Provides common pagination, response processing, and data reading

113

functionality for all stream implementations.

114

"""

115

116

results_per_page = 100 # Default page size for API requests

117

118

def __init__(self, api: API, *args, **kwargs):

119

"""

120

Initialize stream API with core API instance.

121

122

Parameters:

123

- api: Core API instance for making requests

124

"""

125

126

@abstractmethod

127

def list(self, fields: Sequence[str] = None) -> Iterator[dict]:

128

"""

129

Iterate over entities for this stream.

130

131

Parameters:

132

- fields: Optional list of fields to include in response

133

134

Returns:

135

- Iterator[dict]: Iterator yielding individual records

136

"""

137

138

@abstractmethod

139

def process_response(self, response: Dict) -> Iterator[dict]:

140

"""

141

Process Google Directory API response and extract records.

142

143

Parameters:

144

- response: Raw API response dict

145

146

Returns:

147

- Iterator[dict]: Iterator yielding processed records

148

"""

149

150

def _api_get(self, resource: str, params: Dict = None):

151

"""

152

Internal method to call the core API get method.

153

154

Parameters:

155

- resource: API resource name

156

- params: Query parameters for the request

157

158

Returns:

159

- Dict: API response data

160

"""

161

162

def read(self, getter: Callable, params: Dict = None) -> Iterator:

163

"""

164

Read data using getter function with automatic pagination.

165

166

Parameters:

167

- getter: Function to call for each page of data

168

- params: Initial parameters for API request

169

170

Returns:

171

- Iterator: Iterator yielding records across all pages

172

173

Handles nextPageToken pagination automatically.

174

"""

175

```

176

177

### Users API

178

179

API for accessing Google Directory users data.

180

181

```python { .api }

182

class UsersAPI(StreamAPI):

183

"""

184

API for accessing Google Directory users.

185

186

Provides access to user accounts in the Google Workspace domain

187

including profile information, organizational data, and metadata.

188

"""

189

190

def list(self, fields: Sequence[str] = None) -> Iterator[dict]:

191

"""

192

List all users in the Google Workspace domain.

193

194

Parameters:

195

- fields: Optional list of user fields to include

196

197

Returns:

198

- Iterator[dict]: Iterator yielding user records

199

200

Each user record contains standard Google Directory user fields

201

including id, primaryEmail, name, orgUnitPath, etc.

202

"""

203

204

def process_response(self, response: Dict) -> Iterator[dict]:

205

"""

206

Extract users from API response.

207

208

Parameters:

209

- response: Raw API response containing users data

210

211

Returns:

212

- Iterator[dict]: Iterator yielding individual user records

213

"""

214

```

215

216

### Groups API

217

218

API for accessing Google Directory groups data.

219

220

```python { .api }

221

class GroupsAPI(StreamAPI):

222

"""

223

API for accessing Google Directory groups.

224

225

Provides access to groups in the Google Workspace domain including

226

group metadata, settings, and organizational information.

227

"""

228

229

def list(self, fields: Sequence[str] = None) -> Iterator[dict]:

230

"""

231

List all groups in the Google Workspace domain.

232

233

Parameters:

234

- fields: Optional list of group fields to include

235

236

Returns:

237

- Iterator[dict]: Iterator yielding group records

238

239

Each group record contains standard Google Directory group fields

240

including id, email, name, description, etc.

241

"""

242

243

def process_response(self, response: Dict) -> Iterator[dict]:

244

"""

245

Extract groups from API response.

246

247

Parameters:

248

- response: Raw API response containing groups data

249

250

Returns:

251

- Iterator[dict]: Iterator yielding individual group records

252

"""

253

```

254

255

### Group Members API

256

257

API for accessing Google Directory group membership data.

258

259

```python { .api }

260

class GroupMembersAPI(StreamAPI):

261

"""

262

API for accessing Google Directory group memberships.

263

264

Provides access to group membership relationships, iterating through

265

all groups and fetching members for each group.

266

"""

267

268

def list(self, fields: Sequence[str] = None) -> Iterator[dict]:

269

"""

270

List members for all groups in the domain.

271

272

Parameters:

273

- fields: Optional list of member fields to include

274

275

Returns:

276

- Iterator[dict]: Iterator yielding group member records

277

278

Iterates through all groups and fetches membership data for each,

279

yielding individual member records with group context.

280

"""

281

282

def process_response(self, response: Dict) -> Iterator[dict]:

283

"""

284

Extract group members from API response.

285

286

Parameters:

287

- response: Raw API response containing members data

288

289

Returns:

290

- Iterator[dict]: Iterator yielding individual member records

291

292

Returns empty list if no members found in response.

293

"""

294

```

295

296

### Utility Functions

297

298

Helper functions for API error handling and retry logic.

299

300

```python { .api }

301

def rate_limit_handling(error):

302

"""

303

Error handler for backoff retry logic.

304

305

Determines whether API errors should trigger retries based on

306

HTTP status codes and error reasons.

307

308

Parameters:

309

- error: GoogleApiHttpError instance

310

311

Returns:

312

- bool: True if error should not be retried, False to trigger retry

313

314

Retries are disabled for specific rate limit cases:

315

- HTTP 403 with reason 'quotaExceeded'

316

- HTTP 429 with reason 'rateLimitExceeded'

317

318

All other errors will trigger retry with exponential backoff.

319

"""

320

```

321

322

## Usage Examples

323

324

### Direct API Access

325

326

```python

327

from source_google_directory.api import API, UsersAPI, GroupsAPI, GroupMembersAPI

328

329

# OAuth credentials

330

credentials = {

331

"client_id": "your-client-id",

332

"client_secret": "your-client-secret",

333

"refresh_token": "your-refresh-token"

334

}

335

336

# Initialize core API

337

api = API(credentials)

338

339

# Test direct API call

340

response = api.get("users", params={"customer": "my_customer"})

341

print(f"Found {len(response.get('users', []))} users")

342

```

343

344

### Stream API Usage

345

346

```python

347

# Initialize stream APIs

348

users_api = UsersAPI(api)

349

groups_api = GroupsAPI(api)

350

members_api = GroupMembersAPI(api)

351

352

# Iterate through users

353

for user in users_api.list():

354

print(f"User: {user['primaryEmail']} ({user['name']['fullName']})")

355

356

# Iterate through groups

357

for group in groups_api.list():

358

print(f"Group: {group['email']} - {group['name']}")

359

360

# Iterate through group memberships

361

for member in members_api.list():

362

print(f"Member: {member['email']} in group {member.get('groupId', 'N/A')}")

363

```

364

365

### Service Account Configuration

366

367

```python

368

# Service account credentials

369

service_credentials = {

370

"credentials_json": '''{

371

"type": "service_account",

372

"project_id": "your-project",

373

"private_key_id": "...",

374

"private_key": "...",

375

"client_email": "...",

376

"client_id": "...",

377

"auth_uri": "https://accounts.google.com/o/oauth2/auth",

378

"token_uri": "https://oauth2.googleapis.com/token"

379

}''',

380

"email": "admin@yourdomain.com"

381

}

382

383

api = API(service_credentials)

384

```

385

386

## Authentication Requirements

387

388

### Required OAuth Scopes

389

390

```python

391

SCOPES = [

392

"https://www.googleapis.com/auth/admin.directory.user.readonly",

393

"https://www.googleapis.com/auth/admin.directory.group.readonly"

394

]

395

```

396

397

### Prerequisites

398

399

- **OAuth Method**: OAuth 2.0 application configured in Google Cloud Console

400

- **Service Account Method**: Service account with domain-wide delegation enabled

401

- **Admin Access**: Credentials must have Google Workspace admin privileges

402

- **API Enable**: Google Admin SDK Directory API must be enabled in the project

403

404

## Error Handling

405

406

The APIs implement comprehensive error handling with the following features:

407

408

### Retry Logic

409

- **Automatic Retry**: Uses `@backoff.on_exception` decorator with exponential backoff

410

- **Max Retries**: Up to 7 retry attempts for transient errors

411

- **Backoff Strategy**: Exponential backoff starting from 1 second

412

- **Exception Type**: Catches `GoogleApiHttpError` exceptions

413

414

### Rate Limit Handling

415

- **HTTP 403 quotaExceeded**: No retry (permanent failure)

416

- **HTTP 429 rateLimitExceeded**: No retry (permanent failure)

417

- **All other errors**: Automatic retry with exponential backoff

418

- **Custom Handler**: Uses `rate_limit_handling()` function to determine retry eligibility

419

420

### Authentication Management

421

- **OAuth Token Refresh**: Automatic refresh when tokens expire

422

- **Service Account**: Automatic credential validation and delegation setup

423

- **Error Detection**: Graceful handling of authentication failures

424

425

### Error Propagation

426

- **Meaningful Messages**: Detailed error information for debugging

427

- **Health Check Integration**: Connection errors surface through health_check() method

428

- **Exception Details**: Preserves original Google API error context

429

430

### Retry Configuration

431

```python

432

@backoff.on_exception(

433

backoff.expo, # Exponential backoff strategy

434

GoogleApiHttpError, # Exception type to catch

435

max_tries=7, # Maximum retry attempts

436

giveup=rate_limit_handling # Custom retry decision function

437

)

438

```

439

440

Rate-limited requests that exceed quotas are treated as permanent failures and will not be retried, while transient network or server errors trigger automatic retry with increasing delays.