本文档介绍了使用 Google Civic Information API 时需要了解的内容。您可以参阅这份 Civic Info API 常见问题解答,其中包含有关该 API 的一些基本信息,以及用户论坛中的常见问题解答。 此外,您还可以在下方查看有关在选举期间查询选民信息的示例。
向 Google 标识您的应用
您的应用每次向 Google Civic Information API 发送请求时都需要标识自己,方法是将 API 密钥添加到每个请求中。
获取和使用 API 密钥
要获取 API 密钥,请执行以下操作:
- 打开 API 控制台中的“凭据”页面。
-
此 API 支持两种类型的凭据。
创建适合您的项目的凭据:
-
OAuth 2.0:当您的应用请求非公开用户数据时,该应用必须将 OAuth 2.0 令牌随请求一起发送。要获取令牌,您的应用应先发送客户端 ID(也可能需要发送客户端密钥)。您可以为网页应用、服务账号或已安装应用生成 OAuth 2.0 凭据。
注意:由于此 API 没有任何需要 OAuth 2.0 授权的方法,因此您可能只需要获取API 密钥(如下所述)。但是,如果您的应用调用需要用户授权的其他 API,那么您仍然需要 OAuth 2.0 凭据。
如需了解详情,请参阅 OAuth 2.0 文档。
-
API 密钥:未提供 OAuth 2.0 令牌的请求必须发送 API 密钥。 该密钥用于标识您的项目,并提供 API 访问权限、配额和报告。
此 API 支持多种类型的 API 密钥限制。如果您需要的 API 密钥尚不存在,请在 GCP 控制台中创建 API 密钥,方法是:点击创建凭据 > API 密钥。您可以先对密钥设定相关限制,然后再在生产环境中使用密钥,方法是:点击限制密钥,然后选择其中一项限制。
-
为保障 API 密钥的安全,请遵循以安全的方式使用 API 密钥的最佳做法。
在您获得 API 密钥后,您的应用便可在所有请求网址后附加查询参数 key=yourAPIKey
。
API 密钥可以安全地嵌入网址中;不需要进行任何编码。
API 密钥限制
默认情况下,您的 API 密钥不受限制。如果任何人都可以读取此密钥(例如,如果密钥存储在浏览器中)或访问存储此密钥的设备,则会带来安全方面的问题。我们建议您对此 API 密钥设置限制,以防止未经授权的使用。
如需添加限制,请点击已创建的 API 密钥对话框中的限制密钥。系统随即会显示 API 密钥配置面板:

您选择的限制类型取决于您的应用需求:
- 直接与 API 交互(即不通过任何后端或中间件)的 Web 应用应添加 HTTP 引荐来源网址限制。 不过,请注意,此类应用会公开其 API 密钥;建议改用服务账号身份验证方案。
- 无法通过其他方式支持服务账号的后端应用(例如,客户端库中没有受支持语言的嵌入式设备)应添加IP 地址限制,以防范来自不同 IP 地址的客户端的使用。
- Android 应用应添加 Android 应用限制,并添加您的软件包名称和 SHA-1 签名证书指纹。
- iOS 应用应添加 iOS 应用限制,并添加任何 iOS 软件包标识符,以限制对这些 iOS 软件包的 API 调用。
在测试期间,您可能不想设置任何限制。不过,建议您在将应用部署到生产环境后,为此密钥添加限制或将其删除。
electionQuery 示例
下面是一个示例(使用 API 版本“v2”),其中调用了 electionQuery API 来获取有效选举 ID 的列表,然后使用 voterInfoQuery API 和选民的注册地址来获取所选选举的信息。
使用 electionQuery 获取有效的选举 ID 列表:
https://www.googleapis.com/civicinfo/v2/elections?key=<YOUR_API_KEY>
electionQuery 响应:
{ "kind": "civicinfo#electionsqueryresponse", "elections": [ { "id": "2000", "name": "VIP Test Election", "electionDay": "2013-06-06" }, { "id": "2124", "name": "Rhode Island 2012 Primary Election", "electionDay": "2012-09-11" }, { "id": "2126", "name": "Delaware 2012 Primary Election", "electionDay": "2012-09-11" } ] }
使用 curl 执行 voterInfoQuery
使用 curl
针对 VIP 测试选举 ID 2000 和地址为 340 Main St, Venice, CA 90291 的选民发送 voterInfoQuery 请求。您可以参阅 voterInfoQuery 响应。
curl "https://www.googleapis.com/civicinfo/v2/voterinfo?key=<YOUR_API_KEY>&address=340%20Main%20St.%20Venice%20CA&electionId=2000"
使用 JavaScript 版 Google API 客户端库执行 voterInfoQuery
此示例发出了与上一个 curl 示例相同的 voterInfoQuery,但使用了 JavaScript 客户端库。voterInfoQuery 响应与 curl 示例响应相同。
<!doctype html> <html> <head> <script> /** * Build and execute request to look up voter info for provided address. * @param {string} address Address for which to fetch voter info. * @param {function(Object)} callback Function which takes the * response object as a parameter. */ function lookup(address, callback) { /** * Election ID for which to fetch voter info. * @type {number} */ var electionId = 2000; /** * Request object for given parameters. * @type {gapi.client.HttpRequest} */ var req = gapi.client.request({ 'path' : '/civicinfo/v2/voterinfo', 'params' : {'electionId' : electionId, 'address' : address} }); req.execute(callback); } /** * Render results in the DOM. * @param {Object} response Response object returned by the API. * @param {Object} rawResponse Raw response from the API. */ function renderResults(response, rawResponse) { var el = document.getElementById('results'); if (!response || response.error) { el.appendChild(document.createTextNode( 'Error while trying to fetch polling place')); return; } var normalizedAddress = response.normalizedInput.line1 + ' ' + response.normalizedInput.city + ', ' + response.normalizedInput.state + ' ' + response.normalizedInput.zip; if (response.pollingLocations.length > 0) { var pollingLocation = response.pollingLocations[0].address; var pollingAddress = pollingLocation.locationName + ', ' + pollingLocation.line1 + ' ' + pollingLocation.city + ', ' + pollingLocation.state + ' ' + pollingLocation.zip; var normEl = document.createElement('strong'); normEl.appendChild(document.createTextNode( 'Polling place for ' + normalizedAddress + ': ')); el.appendChild(normEl); el.appendChild(document.createTextNode(pollingAddress)); } else { el.appendChild(document.createTextNode( 'Could not find polling place for ' + normalizedAddress)); } } /** * Initialize the API client and make a request. */ function load() { gapi.client.setApiKey('YOUR API KEY GOES HERE'); lookup('1263 Pacific Ave. Kansas City KS', renderResults); } </script> <script src="https://apis.google.com/js/client.js?onload=load"></script> </head> <body> <div id="results"></div> </body> </html>
voterInfoQuery 响应
{ "kind": "civicinfo#voterinforesponse", "status": "success", "election": { "id": "2000", "name": "VIP Test Election", "electionDay": "2025-06-06", "ocdDivisionId": "ocd-division/country:us" }, "normalizedInput": { "line1": "340 Main Street", "city": "Venice", "state": "CA", "zip": "90291" }, "pollingLocations": [ { "address": { "locationName": "WESTMINSTER AVENUE ELEMENTARY SCHOOL", "line1": "1010 ABBOT KINNEY BLVD", "city": "VENICE", "state": "CA", "zip": "90291" }, "pollingHours": "", "latitude": 33.9919351, "longitude": -118.4722031, "startDate": "2024-03-05", "endDate": "2024-03-05", "sources": [ { "name": "Voting Information Project", "official": true } ] }, { "address": { "locationName": "POP UP VOTE CENTER 5", "line1": "12400 IMPERIAL HWY", "city": "NORWALK", "state": "CA", "zip": "90650" }, "latitude": 33.915989, "longitude": -118.0677283, "sources": [ { "name": "Voting Information Project", "official": true } ] } ], "dropOffLocations": [ { "address": { "locationName": "FLEX VOTE CENTER 9", "line1": "12400 IMPERIAL HWY", "city": "NORWALK", "state": "CA", "zip": "90650" }, "latitude": 33.915989, "longitude": -118.0677283, "sources": [ { "name": "Voting Information Project", "official": true } ] }, ], "contests": [ { "type": "General", "ballotTitle": "UNITED STATES REPRESENTATIVE, 36th District", "district": { "name": "36TH US CONGRESSIONAL", "scope": "congressional" }, "numberElected": "1", "numberVotingFor": "1", "ballotPlacement": "103", "sources": [ { "name": "Voting Information Project", "official": true } ], "candidates": [ { "name": "ARIANA HAKAMI", "party": "Party Preference: Republican" }, { "name": "CLAIRE RAGGE ANDERSON", "party": "Party Preference: None" }, { "name": "MELISSA TOOMIM", "party": "Party Preference: Republican" }, { "name": "TED W. LIEU", "party": "Party Preference: Democratic" } ] }, { "type": "ballot-measure", "ballotTitle": "LOS ANGELES CITY MUNICIPAL ELECTION - MEASURE HLA", "district": { "name": "CITY OF LOS ANGELES", "scope": "citywide" }, "ballotPlacement": "116", "referendumTitle": "LOS ANGELES CITY MUNICIPAL ELECTION - MEASURE HLA", "referendumText": "CITY MOBILITY PLAN STREET IMPROVEMENT MEASURES. INITIATIVE ORDINANCE HLA. Shall an ordinance providing that when the City of Los Angeles makes a qualifying improvement to a City-owned street (e.g., a paving project), the City must also install certain street enhancements described in the City's Mobility Plan network of pedestrian, bicycle, transit, and vehicle routes; and requiring the City to provide publicly accessible information regarding street improvements; be adopted?", "referendumPassageThreshold": "MAJORITY OF VOTES CAST", "referendumBallotResponses": [ "YES", "NO" ], "sources": [ { "name": "Voting Information Project", "official": true } ] }, { "type": "General", "ballotTitle": "DISTRICT ATTORNEY", "district": { "name": "LOS ANGELES COUNTY", "scope": "countywide" }, "numberElected": "1", "numberVotingFor": "1", "ballotPlacement": "129", "sources": [ { "name": "Voting Information Project", "official": true } ], "candidates": [ { "name": "GEORGE GASCÓN" }, { "name": "JONATHAN HATAMI" }, { "name": "NATHAN HOCHMAN" }, { "name": "DEBRA ARCHULETA" }, { "name": "JEFF CHEMERINSKY" }, { "name": "ERIC SIDDALL" }, { "name": "MARIA RAMIREZ" }, { "name": "DAN KAPELOVITZ" }, { "name": "LLOYD \"BOBCAT\" MASSON" }, { "name": "JOHN MCKINNEY" }, { "name": "CRAIG J. MITCHELL" }, { "name": "DAVID S. MILTON" } ] } ], "state": [ { "name": "California", "electionAdministrationBody": { "name": "Secretary of State", "electionInfoUrl": "https://www.sos.ca.gov/elections/", "electionRegistrationUrl": "https://registertovote.ca.gov/?t=s", "electionRegistrationConfirmationUrl": "https://voterstatus.sos.ca.gov", "absenteeVotingInfoUrl": "https://elections.cdn.sos.ca.gov/vote-by-mail/replacement-application.pdf", "votingLocationFinderUrl": "https://voterstatus.sos.ca.gov", "ballotInfoUrl": "https://www.sos.ca.gov/elections/ballot-status/wheres-my-ballot/", "correspondenceAddress": { "line1": "1500 11th Street, 5th Floor", "city": "Sacramento", "state": "California", "zip": "95814" } }, "local_jurisdiction": { "name": "Los Angeles", "electionAdministrationBody": { "name": "Registrar-Recorder/County Clerk", "electionInfoUrl": "http://www.lavote.gov/", "electionRegistrationUrl": "http://registertovote.ca.gov/", "electionRegistrationConfirmationUrl": "https://lavote.gov/vrstatus/", "absenteeVotingInfoUrl": "", "ballotInfoUrl": "http://www.lavote.gov/Locator", "physicalAddress": { "locationName": "Registrar-Recorder/County Clerk", "line1": "12400 Imperial Highway", "city": "Norwalk", "state": "CA", "zip": "90650" } }, "sources": [ { "name": "Voting Information Project", "official": true } ] } } ] }