API reference
FOIA Gen's directory of US government bodies that take public records requests, federal to local, and its library of public records laws (federal FOIA, the 50 states and DC), each rule with its citation and the date it was checked against the statute. The directory and the laws are the same for every account and read-only through the API. A contact detail that is being re-checked is left out (null) and named in held until it is confirmed. The rules are information with their sources, not legal advice. With the foia_requests:read scope, a key also reads the account's OWN requests, in every project: where each stands, its deadlines, its correspondence, and its history, the audit trail FOIA Gen keeps of everything that happened to it. Every message that left and every reply that came in is kept with its SHA-256 hash, and the history carries those hashes, so you can archive the trail in your own systems and show later that it was not changed. Requests are written and sent in FOIA Gen, never through the API, and reading one does not mark its replies as read for the people working on it.
/v1/foia/agenciesfoia:readThe directory of US bodies that take public records requests, with the filters FOIA Gen offers in the hub. Confirmed agencies come first, then federal, state and local ones, then by name. Filters combine; level, type and channel take one value or several separated by commas (level=city,county), and an agency matching any of them is listed. A value that is not one of the listed ones is refused with 400 invalid_parameter, never ignored. Retired agencies are left out.
| Name | Type | Description |
|---|---|---|
limitquery | integer | How many to return. 1 to 100. Default 25. |
cursorquery | string | The next_cursor from the previous page. Leave it out for the first page. |
qquery | string | Name, abbreviation, parent department, city or county contains this text, ignoring case (1 to 120 characters). |
levelquery | array of string | Only agencies at these levels of government. One or more of federal, state, county, city, township, school, special, court, tribal, separated by commas. |
statequery | string | Only agencies in this state (two-letter code, case ignored), or US for federal agencies. One of US, AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY. |
with_federalquery | boolean | With state: true adds the federal agencies, which take requests about every state. Default False. |
countyquery | string | Only agencies in this county, without the word County, ignoring case (1 to 80 characters). |
cityquery | string | Only agencies in this city or town, ignoring case (1 to 80 characters). |
typequery | array of string | Only these kinds of body. One or more of police, clerk, executive, corrections, education, transport, health, immigration, justice, courts, legislature, elections, environment, defense, finance, housing, labor, utilities, other, separated by commas. |
channelquery | array of string | Only agencies that take requests this way. An agency whose channel is being re-checked shows it as unknown. One or more of email, portal, mail, fax, unknown, separated by commas. |
verifiedquery | boolean | true: only agencies whose contact details are confirmed. Default False. |
| Field | Type | Description |
|---|---|---|
data | array of object | |
data[].id | string | The agency's id: lower-case letters, digits and hyphens, such as us-doj-fbi. It does not change. |
data[].name | string | |
data[].abbreviation | string or null | |
data[].parent | string or null | The department or government it belongs to. |
data[].level | string | |
data[].state | string | Two-letter state code, or US for a federal agency. |
data[].county | string or null | |
data[].city | string or null | |
data[].type | string | The kind of body. |
data[].topics | array of string | Kinds of records it is known to hold, such as bodycam or contracts. |
data[].channel | string | How it takes requests. unknown when that is not known, or is being re-checked. |
data[].email | string or null | Where requests go by email. |
data[].portal_url | string or null | Its request portal. |
data[].portal_vendor | string or null | Who runs the portal, when known. |
data[].address | string or null | Its mailing address for requests. |
data[].phone | string or null | |
data[].fax | string or null | |
data[].website | string or null | |
data[].reading_room | string or null | Where it publishes records already released. Worth checking before asking. |
data[].median_simple | number or null | Its median days to answer a simple request, as reported to FOIA.gov. Federal agencies only; null when not published. |
data[].median_complex | number or null | The same for a complex request. |
data[].data_year | integer or null | The fiscal year those figures are from. |
data[].nuances | array of object | What to know before filing with this agency, each with where it was read. |
data[].nuances[].text | string | |
data[].nuances[].source | string or null | |
data[].sources | array of object | Where the details came from. |
data[].sources[].label | string | |
data[].sources[].url | string or null | |
data[].confidence | string | verified: confirmed by VeraGen or by a real request. synced: from FOIA.gov. crawled: found on the agency's website, not yet confirmed. unknown: not yet checked. |
data[].verified_at | string or null (date-time) | |
data[].synced_at | string or null (date-time) | When it was last read from FOIA.gov. |
data[].held | array of string | Contact details being re-checked. Each one named here is null in this answer (channel is unknown) until it is confirmed, rather than risk sending a request to the wrong place. |
has_more | boolean | |
next_cursor | string or null |
The codes are listed under Errors.
curl "https://api.veragen.ai/v1/foia/agencies?limit=25&state=TX&with_federal=False&verified=False" \
-H "Authorization: Bearer $VERAGEN_API_KEY"const res = await fetch("https://api.veragen.ai/v1/foia/agencies?limit=25&state=TX&with_federal=False&verified=False", {
headers: { Authorization: `Bearer ${process.env.VERAGEN_API_KEY}` },
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.veragen.ai/v1/foia/agencies",
params={"limit": 25, "state": "TX", "with_federal": false, "verified": false},
headers={"Authorization": f"Bearer {os.environ['VERAGEN_API_KEY']}"},
)
data = res.json(){
"data": [
{
"id": "us-cfpb-cfpb",
"name": "Consumer Financial Protection Bureau",
"abbreviation": "CFPB",
"parent": "Consumer Financial Protection Bureau",
"level": "federal",
"state": "US",
"county": null,
"city": null,
"type": "executive",
"topics": [],
"channel": "email",
"email": null,
"portal_url": "https://www.foia.gov/request/agency-component/833a2183-02d4-4a87-a961-b79ed8d5d8a2/",
"portal_vendor": "FOIA.gov",
"address": "CFPB, Attn: Chief FOIA Officer, 445 12th Street, SW, Washington DC 20024",
"phone": "855-444-3642",
"fax": null,
"website": "http://www.consumerfinance.gov/foia/",
"reading_room": "https://www.consumerfinance.gov/foia-requests/foia-electronic-reading-room/",
"median_simple": 1,
"median_complex": 52.5,
"data_year": 2025,
"nuances": [],
"sources": [
{
"label": "FOIA.gov component record",
"url": "https://www.foia.gov/?id=833a2183-02d4-4a87-a961-b79ed8d5d8a2"
}
],
"confidence": "synced",
"verified_at": null,
"synced_at": "2026-10-05T04:02:11.000Z",
"held": [
"email"
]
},
{
"id": "us-doj-eoir",
"name": "Executive Office for Immigration Review",
"abbreviation": "EOIR",
"parent": "Department of Justice",
"level": "federal",
"state": "US",
"county": null,
"city": null,
"type": "justice",
"topics": [],
"channel": "portal",
"email": null,
"portal_url": "https://www.foia.gov/request/agency-component/bd36709d-06f3-4503-a9d9-8e5f54002ca9/",
"portal_vendor": "FOIA.gov",
"address": "Executive Office for Immigration Review, FOIA Service Center, 5107 Leesburg Pike, Suite 2150, Falls Church VA 22041",
"phone": "703-605-1297",
"fax": null,
"website": "https://www.justice.gov/eoir/freedom-information-act-foia",
"reading_room": "https://www.justice.gov/eoir/foia-library-0",
"median_simple": 9,
"median_complex": 7,
"data_year": 2025,
"nuances": [],
"sources": [
{
"label": "FOIA.gov component record",
"url": "https://www.foia.gov/?id=bd36709d-06f3-4503-a9d9-8e5f54002ca9"
}
],
"confidence": "synced",
"verified_at": null,
"synced_at": "2026-10-05T04:02:11.000Z",
"held": []
}
],
"has_more": true,
"next_cursor": "WzEsMCwiRXhlY3V0aXZlIE9mZmljZSBmb3IgSW1taWdyYXRpb24gUmV2aWV3IiwidXMtZG9qLWVvaXIiXQ"
}/v1/foia/agencies/{id}foia:readOne agency, with a summary of the public records law it follows: federal law for a federal agency, its state's law otherwise (jurisdiction says which). Read the whole rule set with Get a jurisdiction's rules.
| Name | Type | Description |
|---|---|---|
idpath, required | string | The agency's id, from List agencies. |
| Field | Type | Description |
|---|---|---|
id | string | The agency's id: lower-case letters, digits and hyphens, such as us-doj-fbi. It does not change. |
name | string | |
abbreviation | string or null | |
parent | string or null | The department or government it belongs to. |
level | string | |
state | string | Two-letter state code, or US for a federal agency. |
county | string or null | |
city | string or null | |
type | string | The kind of body. |
topics | array of string | Kinds of records it is known to hold, such as bodycam or contracts. |
channel | string | How it takes requests. unknown when that is not known, or is being re-checked. |
email | string or null | Where requests go by email. |
portal_url | string or null | Its request portal. |
portal_vendor | string or null | Who runs the portal, when known. |
address | string or null | Its mailing address for requests. |
phone | string or null | |
fax | string or null | |
website | string or null | |
reading_room | string or null | Where it publishes records already released. Worth checking before asking. |
median_simple | number or null | Its median days to answer a simple request, as reported to FOIA.gov. Federal agencies only; null when not published. |
median_complex | number or null | The same for a complex request. |
data_year | integer or null | The fiscal year those figures are from. |
nuances | array of object | What to know before filing with this agency, each with where it was read. |
nuances[].text | string | |
nuances[].source | string or null | |
sources | array of object | Where the details came from. |
sources[].label | string | |
sources[].url | string or null | |
confidence | string | verified: confirmed by VeraGen or by a real request. synced: from FOIA.gov. crawled: found on the agency's website, not yet confirmed. unknown: not yet checked. |
verified_at | string or null (date-time) | |
synced_at | string or null (date-time) | When it was last read from FOIA.gov. |
held | array of string | Contact details being re-checked. Each one named here is null in this answer (channel is unknown) until it is confirmed, rather than risk sending a request to the wrong place. |
jurisdiction | string | Whose public records law the agency follows: US, or its state. |
rules | object or null | That law, in short; null if the library has no rule set for it. |
rules.code | string | US for federal law, or the state's two-letter code. |
rules.name | string | |
rules.law | string | The name of the law. |
rules.cite | string or null | |
rules.statute_url | string or null | The statute's text. |
rules.deadlines | array of object | What the agency must do by when. Business and working days skip weekends and that jurisdiction's holidays. |
rules.deadlines[].kind | string | What the deadline is for, such as acknowledge, determine, produce, extension or deemed_denial. |
rules.deadlines[].days | number or null | How many days; null when the law says "promptly" or sets no number. |
rules.deadlines[].unit | string | business, working, calendar or none. |
rules.deadlines[].text | string | |
rules.deadlines[].cite | string or null | |
rules.deadlines[].source | string or null | |
rules.status | string | verified: checked against the statute on checked_on. needs_checking: not yet checked; read the statute before relying on it. |
rules.checked_on | string or null (date) | When it was last checked against the statute. |
rules.version | integer | Goes up each time the rule set changes. |
The codes are listed under Errors.
curl "https://api.veragen.ai/v1/foia/agencies/{id}" \
-H "Authorization: Bearer $VERAGEN_API_KEY"const res = await fetch("https://api.veragen.ai/v1/foia/agencies/{id}", {
headers: { Authorization: `Bearer ${process.env.VERAGEN_API_KEY}` },
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.veragen.ai/v1/foia/agencies/{id}",
headers={"Authorization": f"Bearer {os.environ['VERAGEN_API_KEY']}"},
)
data = res.json(){
"id": "us-doj-eoir",
"name": "Executive Office for Immigration Review",
"abbreviation": "EOIR",
"parent": "Department of Justice",
"level": "federal",
"state": "US",
"county": null,
"city": null,
"type": "justice",
"topics": [],
"channel": "portal",
"email": null,
"portal_url": "https://www.foia.gov/request/agency-component/bd36709d-06f3-4503-a9d9-8e5f54002ca9/",
"portal_vendor": "FOIA.gov",
"address": "Executive Office for Immigration Review, FOIA Service Center, 5107 Leesburg Pike, Suite 2150, Falls Church VA 22041",
"phone": "703-605-1297",
"fax": null,
"website": "https://www.justice.gov/eoir/freedom-information-act-foia",
"reading_room": "https://www.justice.gov/eoir/foia-library-0",
"median_simple": 9,
"median_complex": 7,
"data_year": 2025,
"nuances": [],
"sources": [
{
"label": "FOIA.gov component record",
"url": "https://www.foia.gov/?id=bd36709d-06f3-4503-a9d9-8e5f54002ca9"
}
],
"confidence": "synced",
"verified_at": null,
"synced_at": "2026-10-05T04:02:11.000Z",
"held": [],
"jurisdiction": "US",
"rules": {
"code": "US",
"name": "United States (federal)",
"law": "Freedom of Information Act",
"cite": "5 U.S.C. § 552",
"statute_url": "https://www.law.cornell.edu/uscode/text/5/552",
"deadlines": [
{
"kind": "determine",
"days": 20,
"unit": "business",
"text": "The agency must decide whether it will comply within 20 working days (not counting weekends and federal holidays) and tell you its decision, your right to help from its FOIA Public Liaison, and, if adverse, your right to appeal and to dispute-resolution help from OGIS. It may pause the clock once to ask you for reasonably needed information, and again as needed to clarify fees.",
"cite": "5 U.S.C. § 552(a)(6)(A)(i)",
"source": "https://www.law.cornell.edu/uscode/text/5/552"
},
{
"kind": "extension",
"days": 10,
"unit": "working",
"text": "In unusual circumstances (records in field offices, a voluminous request, or consultation with another agency), the agency may extend by up to 10 working days with written notice. If it needs longer, it must offer you a chance to narrow the request or agree on another timeline.",
"cite": "5 U.S.C. § 552(a)(6)(B)",
"source": "https://www.law.cornell.edu/uscode/text/5/552"
}
],
"status": "verified",
"checked_on": "2026-10-05",
"version": 1
}
}/v1/foia/rules/{code}foia:readA jurisdiction's public records law as FOIA Gen applies it: who may ask, whether a reason, writing or a form is required, the deadlines, fees, how to appeal, and notes. Every rule carries its citation and the page it was read from. status says whether the set has been checked against the statute, and checked_on when. This is information with its sources, not legal advice.
| Name | Type | Description |
|---|---|---|
codepath, required | string | US for federal law, or a state's two-letter code (case ignored). One of US, AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY. |
| Field | Type | Description |
|---|---|---|
code | string | US for federal law, or the state's two-letter code. |
name | string | |
law | string | The name of the law. |
cite | string or null | |
statute_url | string or null | The statute's text. |
deadlines | array of object | What the agency must do by when. Business and working days skip weekends and that jurisdiction's holidays. |
deadlines[].kind | string | What the deadline is for, such as acknowledge, determine, produce, extension or deemed_denial. |
deadlines[].days | number or null | How many days; null when the law says "promptly" or sets no number. |
deadlines[].unit | string | business, working, calendar or none. |
deadlines[].text | string | |
deadlines[].cite | string or null | |
deadlines[].source | string or null | |
status | string | verified: checked against the statute on checked_on. needs_checking: not yet checked; read the statute before relying on it. |
checked_on | string or null (date) | When it was last checked against the statute. |
version | integer | Goes up each time the rule set changes. |
who_may_request | object or null | Who may ask. A few states give the right only to their own residents or citizens. |
who_may_request.text | string | The rule in plain English. |
who_may_request.cite | string or null | The citation in the statute. |
who_may_request.source | string or null | The page it was read from. |
who_may_request.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
who_may_request.rule | string or null | For who may request: anyone, or a limit such as residents. |
purpose_required | object or null | Whether you must say why you want the records. |
purpose_required.text | string | The rule in plain English. |
purpose_required.cite | string or null | The citation in the statute. |
purpose_required.source | string or null | The page it was read from. |
purpose_required.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
purpose_required.rule | string or null | For who may request: anyone, or a limit such as residents. |
writing_required | object or null | Whether the request must be in writing. |
writing_required.text | string | The rule in plain English. |
writing_required.cite | string or null | The citation in the statute. |
writing_required.source | string or null | The page it was read from. |
writing_required.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
writing_required.rule | string or null | For who may request: anyone, or a limit such as residents. |
form_required | object or null | Whether a particular form must be used. |
form_required.text | string | The rule in plain English. |
form_required.cite | string or null | The citation in the statute. |
form_required.source | string or null | The page it was read from. |
form_required.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
form_required.rule | string or null | For who may request: anyone, or a limit such as residents. |
fees | object or null | What may be charged. |
fees.text | string | The rule in plain English. |
fees.cite | string or null | The citation in the statute. |
fees.source | string or null | The page it was read from. |
fees.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
fees.rule | string or null | For who may request: anyone, or a limit such as residents. |
appeal | object or null | What to do if the answer is no. |
appeal.text | string | The rule in plain English. |
appeal.cite | string or null | The citation in the statute. |
appeal.source | string or null | The page it was read from. |
appeal.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
appeal.rule | string or null | For who may request: anyone, or a limit such as residents. |
appeal.route | string or null | Where an appeal or complaint goes. |
appeal.deadline_days | number or null | How long you have to appeal, in unit; null when the law sets no deadline. |
appeal.unit | string or null | business, working, calendar or none. |
commercial_certification | object or null | Whether you must certify the records are not for commercial use. |
commercial_certification.text | string | The rule in plain English. |
commercial_certification.cite | string or null | The citation in the statute. |
commercial_certification.source | string or null | The page it was read from. |
commercial_certification.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
commercial_certification.rule | string or null | For who may request: anyone, or a limit such as residents. |
courts_covered | object or null | Whether the courts' records are covered. |
courts_covered.text | string | The rule in plain English. |
courts_covered.cite | string or null | The citation in the statute. |
courts_covered.source | string or null | The page it was read from. |
courts_covered.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
courts_covered.rule | string or null | For who may request: anyone, or a limit such as residents. |
legislature_covered | object or null | Whether the legislature's records are covered. |
legislature_covered.text | string | The rule in plain English. |
legislature_covered.cite | string or null | The citation in the statute. |
legislature_covered.source | string or null | The page it was read from. |
legislature_covered.value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
legislature_covered.rule | string or null | For who may request: anyone, or a limit such as residents. |
notes | array of object | Other things worth knowing. |
notes[].text | string | The rule in plain English. |
notes[].cite | string or null | The citation in the statute. |
notes[].source | string or null | The page it was read from. |
notes[].value | boolean or null | For a yes-or-no rule (is a reason, writing or a form required; are the courts or the legislature covered): the answer. null when it does not apply or is not settled. |
notes[].rule | string or null | For who may request: anyone, or a limit such as residents. |
The codes are listed under Errors.
curl "https://api.veragen.ai/v1/foia/rules/{code}" \
-H "Authorization: Bearer $VERAGEN_API_KEY"const res = await fetch("https://api.veragen.ai/v1/foia/rules/{code}", {
headers: { Authorization: `Bearer ${process.env.VERAGEN_API_KEY}` },
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.veragen.ai/v1/foia/rules/{code}",
headers={"Authorization": f"Bearer {os.environ['VERAGEN_API_KEY']}"},
)
data = res.json(){
"code": "TX",
"name": "Texas",
"law": "Texas Public Information Act",
"cite": "Tex. Gov't Code ch. 552",
"statute_url": "https://statutes.capitol.texas.gov/Docs/GV/htm/GV.552.htm",
"who_may_request": {
"text": "Any person may ask. The agency may check identification but may not ask why you want the records. An agency does not have to accept requests from people in prison or jail (or their non-attorney agents), though it may release records about that person.",
"cite": "Tex. Gov't Code §§ 552.221(a), 552.222(a)-(b), 552.028",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": null,
"rule": "anyone"
},
"purpose_required": {
"text": "You do not have to give a reason. The agency may ask you to clarify or narrow a large request, but it may not ask what you will use the records for.",
"cite": "Tex. Gov't Code § 552.222(b)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": false,
"rule": null
},
"writing_required": {
"text": "Put the request in writing. The deadlines and the attorney general ruling process apply to written requests, delivered by mail, email, hand delivery, or another method the agency has approved (such as fax or its website). If the agency has posted one designated mailing address and one email address, it only has to answer requests sent there, hand-delivered, or sent by a method it has approved.",
"cite": "Tex. Gov't Code §§ 552.234, 552.301(a)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": true,
"rule": null
},
"form_required": {
"text": "No particular form is required. Send the request to the agency's officer for public information, at its designated address if it has one.",
"cite": "Tex. Gov't Code § 552.234",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": false,
"rule": null
},
"deadlines": [
{
"kind": "produce",
"days": null,
"unit": "none",
"text": "The agency must produce public information promptly, meaning as soon as possible within a reasonable time and without delay.",
"cite": "Tex. Gov't Code § 552.221(a)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm"
},
{
"kind": "extension",
"days": 10,
"unit": "business",
"text": "If the agency cannot produce the records within 10 business days, it must tell you so in writing and set a date and hour within a reasonable time when they will be available.",
"cite": "Tex. Gov't Code § 552.221(d)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm"
}
],
"fees": {
"text": "Charges may not exceed the actual cost and follow rules set by the Attorney General. For 50 or fewer pages of paper records, only a per-page charge is allowed, unless the pages are in two or more separate buildings or remote storage. If the charges will be over $40, the agency must first send you a written itemized estimate; you must answer in writing within 10 business days (accept, narrow the request, or say you have complained to the Attorney General) or the request is treated as withdrawn. The agency must waive or reduce charges when release primarily benefits the general public. Agencies may set monthly and yearly limits on free staff time per requester (at least 15 hours a month and 36 hours a year).",
"cite": "Tex. Gov't Code §§ 552.261(a), 552.262(a), 552.2615, 552.267(a), 552.275(a)-(b)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": null,
"rule": null
},
"appeal": {
"text": "Texas has no internal appeal. If the agency does not comply, you can file a signed written complaint with the district or county attorney where the agency is located (for state agencies, the Travis County district attorney), who must decide within 30 days whether to act; complain to the Attorney General about overcharges; or sue for a writ of mandamus in district court in the county of the agency's main office. No filing deadline for these is set in the Act.",
"cite": "Tex. Gov't Code §§ 552.3215(e)-(i), 552.269(a), 552.321",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": null,
"rule": null,
"route": "No administrative appeal. Complaint to the county or district attorney (or Attorney General); overcharge complaint to the Attorney General; mandamus suit in district court",
"deadline_days": null,
"unit": "none"
},
"commercial_certification": {
"text": "The Act has no general commercial-use certification. The agency may not ask how you will use the records.",
"cite": "Tex. Gov't Code § 552.222(a)-(b)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": false,
"rule": null
},
"courts_covered": {
"text": "The judiciary is not a governmental body under the Act, so court records are not requested under it.",
"cite": "Tex. Gov't Code § 552.003(1)(B)(i)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": false,
"rule": null
},
"legislature_covered": {
"text": "Boards, committees, agencies and offices within or created by the legislative branch are governmental bodies under the Act. Some legislative records may still fall under exceptions.",
"cite": "Tex. Gov't Code § 552.003(1)(A)(i)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": true,
"rule": null
},
"notes": [
{
"text": "Every governmental body must report its designated request mailing address and email address to the Attorney General by October 1 each year, and the Attorney General publishes them in a public online database. Use that address.",
"cite": "Tex. Gov't Code § 552.234(c)-(f)",
"source": "https://tcss.legis.texas.gov/resources/GV/htm/GV.552.htm",
"value": null,
"rule": null
}
],
"status": "verified",
"checked_on": "2026-10-05",
"version": 1
}/v1/foia/requestsfoia_requests:readThe account's FOIA Gen requests in every project, most recently changed first. Deleted requests are left out. Filters combine: view picks the same groups as the tabs in FOIA Gen (needs_you: a draft, a fee letter or question to answer, or a denial whose appeal window is open; waiting: with the agency; overdue: a deadline has passed; closed), status one exact status, project_id one project, and updated_since only requests changed at or after a time, for keeping another system in step. A value that is not one of the listed ones is refused with 400 invalid_parameter, never ignored.
| Name | Type | Description |
|---|---|---|
limitquery | integer | How many to return. 1 to 100. Default 25. |
cursorquery | string | The next_cursor from the previous page. Leave it out for the first page. |
project_idquery | string (uuid) | Only requests in this project. |
statusquery | string | Only requests with exactly this status. One of draft, sending, sent, acknowledged, in_progress, fee_needs_you, needs_reply, partly_released, released, denied, no_records, appealed, closed, withdrawn. |
viewquery | string | Only requests in this group, as FOIA Gen's tabs show them. One of needs_you, waiting, closed, overdue, all. Default all. |
updated_sincequery | string | Only requests changed at or after this time: a date (YYYY-MM-DD, UTC) or an ISO-8601 date and time with a zone. |
| Field | Type | Description |
|---|---|---|
data | array of object | |
data[].id | string (uuid) | |
data[].project_id | string (uuid) | The project the request is in. |
data[].title | string | |
data[].status | string | Where the request stands, as FOIA Gen shows it. sending that has lasted more than a few minutes is flagged by send_unconfirmed. |
data[].send_unconfirmed | boolean | true when a send started but could not be confirmed: check with the agency before sending again. A person resolves it in FOIA Gen. |
data[].agency | object or null | The agency it is addressed to, as it was when the request was written; null before one is chosen. |
data[].agency.id | string | The agency's id in the directory (Get an agency). |
data[].agency.name | string | |
data[].agency.level | string or null | |
data[].agency.state | string or null | Two-letter state code, or US. |
data[].jurisdiction | string or null | Whose law applies: US, or the state's two-letter code. |
data[].channel | string or null | How it goes to the agency. |
data[].tracking_number | string or null | The agency's own reference for it, once known. |
data[].next_deadline | object or null | The soonest open (or missed) deadline, or null. |
data[].next_deadline.kind | string | |
data[].next_deadline.due_on | string or null (date) | |
data[].sent_at | string or null (date-time) | |
data[].created_at | string (date-time) | |
data[].updated_at | string (date-time) | When anything about it last changed. Lists are ordered by it, newest first. |
has_more | boolean | |
next_cursor | string or null |
The codes are listed under Errors.
curl "https://api.veragen.ai/v1/foia/requests?limit=25&view=all" \
-H "Authorization: Bearer $VERAGEN_API_KEY"const res = await fetch("https://api.veragen.ai/v1/foia/requests?limit=25&view=all", {
headers: { Authorization: `Bearer ${process.env.VERAGEN_API_KEY}` },
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.veragen.ai/v1/foia/requests",
params={"limit": 25, "view": "all"},
headers={"Authorization": f"Bearer {os.environ['VERAGEN_API_KEY']}"},
)
data = res.json(){
"data": [
{
"id": "7e3a9c41-2b6d-4f80-9a15-c3d4e5f60718",
"project_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"title": "Use-of-force reports, 2024 to 2025",
"status": "acknowledged",
"send_unconfirmed": false,
"agency": {
"id": "tx-austin-police-3f9a1c",
"name": "Austin Police Department",
"level": "city",
"state": "TX"
},
"jurisdiction": "TX",
"channel": "email",
"tracking_number": "R012345-100526",
"next_deadline": {
"kind": "decide",
"due_on": "2026-10-19"
},
"sent_at": "2026-10-05T14:02:11.482Z",
"created_at": "2026-10-05T13:40:02.115Z",
"updated_at": "2026-10-06T09:15:44.903Z"
}
],
"has_more": false,
"next_cursor": null
}/v1/foia/requests/{id}foia_requests:readOne request: the letter, the agency it went to, its deadlines with the rule each comes from, and its correspondence, oldest first. Each message carries its text as plain text (never the agency's HTML), its attachments' names, sizes and hashes, and the SHA-256 of the exact message stored. The latest 50 messages are included; messages_truncated says when there are more, and the history has every one.
| Name | Type | Description |
|---|---|---|
idpath, required | string (uuid) | The request's id, from List requests. |
| Field | Type | Description |
|---|---|---|
id | string (uuid) | |
project_id | string (uuid) | The project the request is in. |
title | string | |
status | string | Where the request stands, as FOIA Gen shows it. sending that has lasted more than a few minutes is flagged by send_unconfirmed. |
send_unconfirmed | boolean | true when a send started but could not be confirmed: check with the agency before sending again. A person resolves it in FOIA Gen. |
agency | object or null | The agency it is addressed to, with the contact details it was written for; null before one is chosen. |
agency.id | string | |
agency.name | string | |
agency.level | string or null | |
agency.state | string or null | |
agency.parent | string or null | |
agency.email | string or null | |
agency.portal_url | string or null | |
agency.address | string or null | |
jurisdiction | string or null | Whose law applies: US, or the state's two-letter code. |
channel | string or null | How it goes to the agency. |
tracking_number | string or null | The agency's own reference for it, once known. |
sent_at | string or null (date-time) | |
created_at | string (date-time) | |
updated_at | string (date-time) | When anything about it last changed. Lists are ordered by it, newest first. |
description | string | The records asked for, in the requester's words. |
subject | string | |
body | string | The letter, as plain text. |
certified_no | string or null | The certified-mail number, for a request sent by post. |
submitted_at | string or null (date-time) | When it was recorded as filed on the agency's portal. |
mailed_at | string or null (date-time) | When it was recorded as posted. |
acknowledged_at | string or null (date-time) | |
closed_at | string or null (date-time) | |
deadlines | array of object | Its deadlines, soonest first, each with the rule it comes from. |
deadlines[].id | string (uuid) | |
deadlines[].kind | string | Whose move it is by then: the agency's (acknowledge, decide, extended) or yours (fee_reply, clarify_reply, still_interested, appeal, court). |
deadlines[].due_on | string or null (date) | null while it is paused or has no fixed date. |
deadlines[].basis | string | How the date was worked out. |
deadlines[].cite | string or null | The statute it comes from. |
deadlines[].source | string or null | |
deadlines[].status | string | |
messages | array of object | The correspondence, oldest first: the latest 50 messages. |
messages[].id | string (uuid) | |
messages[].direction | string | out: sent from FOIA Gen. in: a reply that came in. |
messages[].channel | string | |
messages[].from | string or null | |
messages[].to | string or null | |
messages[].subject | string | |
messages[].text | string | The message as plain text. An agency's HTML email is turned into text; HTML is never returned. |
messages[].status | string | sent or failed for a message out; received for a reply. |
messages[].sha256 | string or null | The SHA-256 of the exact message as stored. |
messages[].attachments | array of object | |
messages[].attachments[].name | string | |
messages[].attachments[].content_type | string or null | |
messages[].attachments[].size | integer or null | In bytes. |
messages[].attachments[].sha256 | string or null | The SHA-256 of the file as kept. |
messages[].attachments[].stored | boolean | false when the file could not be kept (too large, or sent inline). |
messages[].received_at | string or null (date-time) | |
messages[].created_at | string (date-time) | |
messages_truncated | boolean | true when there are more than 50 messages and the earliest are not in messages. The history (List a request's history) has every one. |
The codes are listed under Errors.
curl "https://api.veragen.ai/v1/foia/requests/{id}" \
-H "Authorization: Bearer $VERAGEN_API_KEY"const res = await fetch("https://api.veragen.ai/v1/foia/requests/{id}", {
headers: { Authorization: `Bearer ${process.env.VERAGEN_API_KEY}` },
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.veragen.ai/v1/foia/requests/{id}",
headers={"Authorization": f"Bearer {os.environ['VERAGEN_API_KEY']}"},
)
data = res.json(){
"id": "7e3a9c41-2b6d-4f80-9a15-c3d4e5f60718",
"project_id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"title": "Use-of-force reports, 2024 to 2025",
"status": "acknowledged",
"send_unconfirmed": false,
"agency": {
"id": "tx-austin-police-3f9a1c",
"name": "Austin Police Department",
"level": "city",
"state": "TX",
"parent": "City of Austin",
"email": "apdrecords@austin.example",
"portal_url": null,
"address": null
},
"jurisdiction": "TX",
"channel": "email",
"tracking_number": "R012345-100526",
"sent_at": "2026-10-05T14:02:11.482Z",
"created_at": "2026-10-05T13:40:02.115Z",
"updated_at": "2026-10-06T09:15:44.903Z",
"description": "Every use-of-force report filed by officers from 1 January 2024 to 31 December 2025, with the supervisor review attached to each.",
"subject": "Public Information Act request: use-of-force reports, 2024 to 2025",
"body": "Dear Public Information Officer,\n\nUnder the Texas Public Information Act, Tex. Gov't Code ch. 552, I request copies of every use-of-force report filed from 1 January 2024 to 31 December 2025...\n\nThank you,\nJordan Reyes",
"certified_no": null,
"submitted_at": null,
"mailed_at": null,
"acknowledged_at": "2026-10-06T09:15:44.903Z",
"closed_at": null,
"deadlines": [
{
"id": "b2c3d4e5-f607-4819-8a2b-3c4d5e6f7081",
"kind": "decide",
"due_on": "2026-10-19",
"basis": "10 business days from receipt to produce the records or say when they will be ready.",
"cite": "Tex. Gov't Code § 552.221(d)",
"source": "https://statutes.capitol.texas.gov/Docs/GV/htm/GV.552.htm",
"status": "open"
}
],
"messages": [
{
"id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"direction": "out",
"channel": "email",
"from": "r-k3v9q2m7x1c8w4z6p0t5b2n8@requests.veragen.ai",
"to": "apdrecords@austin.example",
"subject": "Public Information Act request: use-of-force reports, 2024 to 2025",
"text": "Dear Public Information Officer,\n\nUnder the Texas Public Information Act...",
"status": "sent",
"sha256": "9f2c4e1a7b3d5f60812a4c6e8b0d2f4a6c8e0b2d4f6a8c0e2b4d6f8a0c2e4b6d",
"attachments": [],
"received_at": null,
"created_at": "2026-10-05T14:02:11.482Z"
},
{
"id": "d2e3f4a5-b6c7-4d8e-9fa0-1b2c3d4e5f60",
"direction": "in",
"channel": "email",
"from": "apdrecords@austin.example",
"to": "r-k3v9q2m7x1c8w4z6p0t5b2n8@requests.veragen.ai",
"subject": "RE: Public Information Act request [R012345-100526]",
"text": "Your request has been received and assigned reference R012345-100526.",
"status": "received",
"sha256": "1a3c5e7f9b2d4f6a8c0e1b3d5f7a9c2e4b6d8f0a1c3e5b7d9f2a4c6e8b0d1f3a",
"attachments": [
{
"name": "acknowledgement.pdf",
"content_type": "application/pdf",
"size": 48213,
"sha256": "5d7f9a1c3e5b7d9f0a2c4e6b8d0f1a3c5e7b9d2f4a6c8e0b1d3f5a7c9e2b4d6f",
"stored": true
}
],
"received_at": "2026-10-06T09:15:40.000Z",
"created_at": "2026-10-06T09:15:40.000Z"
}
],
"messages_truncated": false
}/v1/foia/requests/{id}/eventsfoia_requests:readEverything that happened to a request, OLDEST first: created, drafted, sent, replies in, status changes, deadlines, documents, notes. The history is append-only: nothing in it is ever changed or removed, so a page you have read stays true. When an event kept a copy of what was sent or received (stored), sha256 is the SHA-256 of that exact copy. Because the history only grows, an archive can read it to the end once and, on later reads, keep only the events whose id it does not have yet.
| Name | Type | Description |
|---|---|---|
idpath, required | string (uuid) | The request's id, from List requests. |
limitquery | integer | How many to return. 1 to 100. Default 25. |
cursorquery | string | The next_cursor from the previous page. Leave it out for the first page. |
| Field | Type | Description |
|---|---|---|
data | array of object | |
data[].id | string (uuid) | |
data[].at | string (date-time) | |
data[].actor | string | Who did it: a member of the account, the agency (a reply from its own address), an unconfirmed sender (a message from any other address, filed but changing nothing; detail.from has the address), or FOIA Gen itself (deadlines, reminders). |
data[].actor_email | string or null | The member's sign-in email; null for the agency, FOIA Gen, or someone no longer in the account. |
data[].kind | string | |
data[].summary | string | One line, as the history in FOIA Gen shows it. |
data[].detail | object | Facts particular to the kind, such as to and message_id for a send or from and to for a status change. The keys vary by kind and more may be added. |
data[].sha256 | string or null | For a stored event: the SHA-256 of the exact copy kept. |
data[].stored | boolean | true when a copy of what was sent or received was kept with this event. |
has_more | boolean | |
next_cursor | string or null |
The codes are listed under Errors.
curl "https://api.veragen.ai/v1/foia/requests/{id}/events?limit=25" \
-H "Authorization: Bearer $VERAGEN_API_KEY"const res = await fetch("https://api.veragen.ai/v1/foia/requests/{id}/events?limit=25", {
headers: { Authorization: `Bearer ${process.env.VERAGEN_API_KEY}` },
});
const data = await res.json();import os, requests
res = requests.get(
"https://api.veragen.ai/v1/foia/requests/{id}/events",
params={"limit": 25},
headers={"Authorization": f"Bearer {os.environ['VERAGEN_API_KEY']}"},
)
data = res.json(){
"data": [
{
"id": "e1f2a3b4-c5d6-4e7f-8091-a2b3c4d5e6f7",
"at": "2026-10-05T13:40:02.115Z",
"actor": "member",
"actor_email": "jordan@newsroom.example",
"kind": "created",
"summary": "Started this request to Austin Police Department.",
"detail": {
"agency_id": "tx-austin-police-3f9a1c",
"template_id": null
},
"sha256": null,
"stored": false
},
{
"id": "f2a3b4c5-d6e7-4f80-91a2-b3c4d5e6f708",
"at": "2026-10-05T14:02:11.482Z",
"actor": "member",
"actor_email": "jordan@newsroom.example",
"kind": "sent",
"summary": "Sent by email to apdrecords@austin.example.",
"detail": {
"to": "apdrecords@austin.example",
"channel": "email",
"message_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f"
},
"sha256": "9f2c4e1a7b3d5f60812a4c6e8b0d2f4a6c8e0b2d4f6a8c0e2b4d6f8a0c2e4b6d",
"stored": true
},
{
"id": "a3b4c5d6-e7f8-4091-a2b3-c4d5e6f70819",
"at": "2026-10-06T09:15:40.311Z",
"actor": "agency",
"actor_email": null,
"kind": "message_in",
"summary": "Reply from apdrecords@austin.example.",
"detail": {
"from": "apdrecords@austin.example"
},
"sha256": "1a3c5e7f9b2d4f6a8c0e1b3d5f7a9c2e4b6d8f0a1c3e5b7d9f2a4c6e8b0d1f3a",
"stored": true
}
],
"has_more": false,
"next_cursor": null
}