Lambda Project Setup
Goal
Initialize a SAM project containing two Lambda functions (EDGAR file refresh and document retrieval), configure template.yaml for Python 3.12, and deploy the stack so that both functions run in AWS with their dependencies correctly packaged.
Contract
Your Lambda 2 (document retrieval) function accepts requests and returns responses conforming to the Lambda Contract.
The model used for inference is defined in Models. Link there rather than hardcoding an identifier.
Required Reading
Constraints
SAM CLI only. Use
sam init,sam build, andsam deployfor all infrastructure. No console-click deployments; no raw CloudFormation uploads.Python 3.12 runtime. Both functions must declare
Runtime: python3.12intemplate.yaml.Package
requestsexplicitly. Therequestslibrary is not included in the Lambda Python runtime. List it in arequirements.txtat each function's root so thatsam buildbundles it into the deployment artifact.Custom User-Agent on all SEC EDGAR requests. The SEC Fair Access policy requires a declared identity. Every HTTP call to
sec.govmust include aUser-Agentheader with your name and contact email. Recall the pattern from the CIK Lookup project.No comments inside JSON blocks. JSON does not support comments. Configuration examples in your code (event payloads,
template.yamloutputs) must contain only valid JSON.Lambda I/O matches the contract. Lambda 2 must accept exactly the fields defined in the request schema and return the response schema. Do not invent additional fields or rename existing ones.
S3 bucket versioning enabled. Lambda 1 uploads to a versioned S3 bucket. Configure this in
template.yaml, not after the fact in the console.EventBridge schedule for Lambda 1. Use a SAM
Scheduleevent to trigger the daily refresh. Note: EventBridge cron expressions evaluate in UTC.
Acceptance Criteria
sam buildcompletes without errors.sam deploy --guidedcreates the CloudFormation stack with both functions, an S3 bucket (versioning enabled), and an EventBridge rule.Lambda 1 executes on schedule, downloads
https://www.sec.gov/files/company_tickers.json, and uploads it to S3. CloudWatch logs show a successful invocation.Lambda 2, when invoked with a valid contract request, returns a well-formed response. When invoked with an invalid
periodvalue, it returns a validation error.All SEC EDGAR HTTP requests include a
User-Agentheader matching your declared identity.sam local invokewith a sample event file produces a response locally before deploying.
Hints
Project initialization
sam init offers templates. Choose the "Hello World" Python template, then replace the generated function code with your own. The directory structure SAM creates is significant: each function lives in its own subdirectory with its own requirements.txt.
template.yaml structure
You need two AWS::Serverless::Function resources. Each specifies Runtime, Handler, CodeUri (pointing to the function subdirectory), and its event source. Lambda 1 gets a Schedule event; Lambda 2 gets no event source in the template (it is invoked programmatically).
The S3 bucket is a separate AWS::S3::Bucket resource with VersioningConfiguration set.
Note: both functions inherit Runtime: python3.12 from the Globals section. Each function's CodeUri points to a subdirectory containing its own requirements.txt with requests listed.
Packaging requests
Create a requirements.txt in each function's CodeUri directory containing requests. When you run sam build, SAM installs those dependencies into the build artifact automatically. Verify by checking the .aws-sam/build/ directory.
User-Agent header
Pass a headers dict to every requests.get() call targeting sec.gov:
This is the same pattern you used in the CIK module. Extract it to a constant or environment variable so it is easy to update.
Local testing
Create a JSON file (e.g., events/retrieve.json) containing a valid contract request. Then:
This runs the function in a Docker container matching the Lambda runtime. If you see No module named 'requests', run sam build first.
EventBridge UTC gotcha
SAM Schedule expressions use UTC. If you set cron(0 12 * * ? *) expecting noon local time, it fires at noon UTC. Adjust for your timezone during testing, or set a frequent schedule (every 5 minutes) to verify quickly, then switch to daily.
Last verified: 2026-06
Last updated