Skip to main content

gRPC API Testing

This guide provides comprehensive examples for testing the PermitProof gRPC API. The API can be accessed in two ways:

  1. Direct gRPC Backend - Calls the Cloud Run gRPC service directly
  2. gRPC via ESPv2 Gateway - Calls through the ESPv2 proxy (Cloud Endpoints)

Authentication

Direct gRPC Backend

Direct gRPC calls require only the authorization header:

# Generate Firebase bearer token
CODEPROOF_FIREBASE_TOKEN=$(./firebase-token-generator/generate-token.sh sanchos101@gmail.com)

# Set gRPC server host (dev environment)
GRPC_SERVER_HOST=construction-code-expert-dev-856365345080.us-central1.run.app

gRPC via ESPv2 Gateway

ESPv2 gateway calls require both authorization and x-original-authorization headers:

# Generate Firebase bearer token
CODEPROOF_FIREBASE_TOKEN=$(./firebase-token-generator/generate-token.sh sanchos101@gmail.com)

# Set ESPv2 service host (dev environment)
ESP_SERVICE_HOST=construction-code-expert-esp2-dev-6yieikr6ca-uc.a.run.app

Key Difference: ESPv2 requires both headers for proper authentication flow through the gateway.

Service Discovery

List available services and methods using gRPC reflection:

# List all services (direct gRPC)
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
${GRPC_SERVER_HOST}:443 \
list

# Describe a specific service
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
${GRPC_SERVER_HOST}:443 \
describe org.codetricks.construction.code.assistant.service.ArchitecturalPlanService

# List services via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
${ESP_SERVICE_HOST}:443 \
list

Note: Service discovery works because gRPC reflection is enabled on the server.

ArchitecturalPlanService

GetArchitecturalPlan

Get project metadata and page list:

# Direct gRPC
grpcurl -import-path src/main/proto \
-proto src/main/proto/api.proto \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlan

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlan

GetArchitecturalPlanPagePdf

Retrieve PDF content for a specific page:

# Direct gRPC (note: use -max-msg-sz for large PDFs)
grpcurl -import-path src/main/proto \
-proto src/main/proto/api.proto \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14", "page_number": 1}' \
-max-msg-sz $((10 * 1024 * 1024)) \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlanPagePdf

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14", "page_number": 1}' \
-max-msg-sz $((10 * 1024 * 1024)) \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlanPagePdf

Note: Some PDF pages can exceed 4MB (default gRPC message size), so -max-msg-sz is required.

ArchitecturalPlanReviewService

GetApplicableCodeSections

Get applicable code sections for a specific page (from GitHub Issue #182):

# Set project variables
PROJECT_ID="US.CA.SanJose-1550-Tech.Dr-rev2002-07-09"
PAGE_NUMBER=2
ICC_BOOK_ID="3701"

# Direct gRPC (using heredoc for readability)
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d @ \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanReviewService/GetApplicableCodeSections \
<<EOF
{
"architectural_plan_id": "${PROJECT_ID}",
"page_number": ${PAGE_NUMBER},
"icc_book_id": "${ICC_BOOK_ID}"
}
EOF

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d @ \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanReviewService/GetApplicableCodeSections \
<<EOF
{
"architectural_plan_id": "${PROJECT_ID}",
"page_number": ${PAGE_NUMBER},
"icc_book_id": "${ICC_BOOK_ID}"
}
EOF

Note: Proto path and imports can be omitted when using service discovery (reflection enabled).

GetIccBookTableOfContents

Get the table of contents for an ICC book:

# Direct gRPC
grpcurl -import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/api.proto \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"icc_book_id": "2217"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanReviewService/GetIccBookTableOfContents

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"icc_book_id": "2217"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanReviewService/GetIccBookTableOfContents

CodeApplicabilityService

StartAsyncCodeApplicabilityAnalysis

Trigger asynchronous code applicability analysis (from GitHub Issue #179):

# Direct gRPC
grpcurl -import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/code_applicability.proto \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{
"architectural_project_id": "US.CA.SanJose-1550-Tech.Dr-rev2002-07-09",
"page_number": 2,
"icc_book_id": "3701",
"max_relevant_chapters": 5
}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.applicability.CodeApplicabilityService/StartCodeApplicabilityAnalysisTask

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{
"architectural_project_id": "US.CA.SanJose-1550-Tech.Dr-rev2002-07-09",
"page_number": 2,
"icc_book_id": "3701",
"max_relevant_chapters": 5
}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.applicability.CodeApplicabilityService/StartCodeApplicabilityAnalysisTask

Expected Response:

{
"taskId": "550e8400-e29b-41d4-a716-446655440000",
"success": true,
"message": "Code applicability analysis started"
}

ComplianceCodeSearchService

GetIccCodeSearchResults

Perform semantic search across ICC code sections:

# Direct gRPC
grpcurl -import-path src/main/proto \
-import-path env/dependencies/googleapis \
-proto src/main/proto/api.proto \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{
"icc_book_id": "2217",
"query": "Cooling towers located on a roof of a building shall be constructed of non-combustible materials when the base area of the cooling tower is greater than how many square feet?",
"max_results": 3
}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ComplianceCodeSearchService/GetIccCodeSearchResults

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{
"icc_book_id": "2217",
"query": "Cooling towers",
"max_results": 3
}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.ComplianceCodeSearchService/GetIccCodeSearchResults

RBACService

GetUserProjects

List projects accessible to a user (from GitHub Issue #136):

# Direct gRPC
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"user_email": "sanchos101@gmail.com"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.auth.rbac.RBACService/GetUserProjects

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"user_email": "sanchos101@gmail.com"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.auth.rbac.RBACService/GetUserProjects

GetProjectMembers

Get list of users who have access to a project:

# Direct gRPC
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"project_id": "R2024.0091-2024-10-14"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.auth.rbac.RBACService/GetProjectMembers

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"project_id": "R2024.0091-2024-10-14"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.auth.rbac.RBACService/GetProjectMembers

ArchitecturalPlanWriteService

CreateArchitecturalPlan

Create a new project (from GitHub Issue #214):

# Direct gRPC
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"project_id": "TestProject", "project_name": "Test Project"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanWriteService/CreateArchitecturalPlan

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"project_id": "TestProject2", "project_name": "Test Project 2"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanWriteService/CreateArchitecturalPlan

IccBookInfoService

GetIccBookInfo

Get metadata for a specific ICC book (from GitHub Issue #185):

# Direct gRPC
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"document_id": "3701"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.io.icc.api.IccBookInfoService/GetIccBookInfo

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"document_id": "3701"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.io.icc.api.IccBookInfoService/GetIccBookInfo

GetAvailableBookInfo

List all available ICC books:

# Direct gRPC
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.io.icc.api.IccBookInfoService/GetAvailableBookInfo

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.construction.code.assistant.io.icc.api.IccBookInfoService/GetAvailableBookInfo

AccessControlListService

GetAuthorizationStatus

Check if a user is authorized to access the application:

# Direct gRPC
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"client_email": "sanchos101@gmail.com"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.auth.AccessControlListService/GetAuthorizationStatus

# Via ESPv2
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-H "x-original-authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"client_email": "sanchos101@gmail.com"}' \
${ESP_SERVICE_HOST}:443 \
org.codetricks.auth.AccessControlListService/GetAuthorizationStatus

Common Book IDs

For testing code applicability and compliance APIs:

  • 2217 - IBC 2021
  • 3123 - IBC 2021 (NJ Edition)
  • 3701 - California Building Code 2022
  • 3815 - Florida Building Code 2023
  • 3100 - ICC/ANSI A117.1-2017 (Accessibility)
  • 1156 - ICC 300-2017
  • 3757 - IRC 2021 (International Residential Code)

Troubleshooting

Authentication Errors

Problem: Code: Unauthenticated or Invalid JWT format

Solutions:

  1. Regenerate token: Tokens expire after 1 hour
  2. Check header format: Use lowercase authorization (not Authorization)
  3. Verify user is allowlisted: Check Google Group membership
  4. ESPv2 calls: Ensure both headers are present

Service Not Found Errors

Problem: Code: Unimplemented or service not found

Solutions:

  1. Check service name: Use full package path
  2. Verify deployment: Ensure latest backend is deployed
  3. Check ESPv2 config: Verify service is registered in api_config.yaml
  4. Use service discovery: Run grpcurl list to see available services

Proto Import Errors

Problem: cannot resolve import or proto file not found

Solutions:

  1. Use service discovery: Omit -import-path and -proto flags when reflection is enabled
  2. Check googleapis: Ensure env/dependencies/googleapis is cloned
  3. Verify proto paths: Use correct relative paths from project root

Message Size Errors

Problem: resource exhausted or message too large

Solutions:

  1. Increase message size: Use -max-msg-sz $((10 * 1024 * 1024)) for 10MB limit
  2. Check PDF size: Some pages may exceed limits
  3. Use streaming: Consider implementing streaming RPCs for large data

Local Development Testing

For testing against localhost (from GitHub Issue #129):

# Start local gRPC server
source env/dev/setvars.sh
mvn exec:java -Dexec.mainClass="org.codetricks.construction.code.assistant.service.ArchitecturalPlanServer"

# Test against localhost (no TLS, use -plaintext)
grpcurl -plaintext \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
localhost:8080 \
list

# Call a method on localhost
grpcurl -plaintext \
-H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14"}' \
localhost:8080 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlan

Note: Local development uses -plaintext flag (no TLS). Cloud Run deployments use TLS on port 443.

Advanced Usage

Using Heredoc for Complex Requests

For requests with many fields or complex JSON, use heredoc syntax:

grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d @ \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanReviewService/GetApplicableCodeSections \
<<EOF
{
"architectural_plan_id": "${PROJECT_ID}",
"page_number": ${PAGE_NUMBER},
"icc_book_id": "${ICC_BOOK_ID}"
}
EOF

Piping Output to jq

Format and filter JSON responses using jq:

grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" \
-d '{"architectural_plan_id": "R2024.0091-2024-10-14"}' \
${GRPC_SERVER_HOST}:443 \
org.codetricks.construction.code.assistant.service.ArchitecturalPlanService/GetArchitecturalPlan \
| jq '.pages[] | {pageNumber, pageTitle}'

Testing Multiple Environments

# Test against dev
GRPC_SERVER_HOST=construction-code-expert-dev-856365345080.us-central1.run.app
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" ...

# Test against test
GRPC_SERVER_HOST=construction-code-expert-test-856365345080.us-central1.run.app
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" ...

# Test against demo
GRPC_SERVER_HOST=construction-code-expert-demo-856365345080.us-central1.run.app
grpcurl -H "authorization: Bearer ${CODEPROOF_FIREBASE_TOKEN}" ...