webium / silverstripe-indeed-apply
Indeed Apply integration for SilverStripe - receive job applications via Indeed's Quick Apply feature
Installs: 13
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Type:silverstripe-vendormodule
pkg:composer/webium/silverstripe-indeed-apply
Requires
- php: >=7.4
- silverstripe/cms: ^4.0 || ^5.0
README
This module enables receiving job applications from Indeed Apply via a POST endpoint.
What does this module do?
This module:
- Provides an endpoint (
/indeed-apply) where Indeed Apply applications can be sent - Logs all incoming requests for debugging
- Stores applications in the database for further processing
- Provides a CMS interface for managing applications and logs
Installation
- Install via Composer:
composer require webium/silverstripe-indeed-apply
- Run dev/build to create database tables:
vendor/bin/sake dev/build flush=1
Database Tables
After installation, the following tables are created:
IndeedApply- Contains the applicationsIndeedApplyLog- Contains logs of all requests
Endpoint
The module creates a POST endpoint at:
https://yourdomain.com/indeed-apply
Customizing the Endpoint URL
You can customize the endpoint URL by editing your project's config file:
app/_config/indeed-apply-custom.yml:
--- Name: indeed-apply-custom After: 'indeed-apply-config' --- # Custom route configuration SilverStripe\Control\Director: rules: 'jobs/apply': 'Webium\IndeedApply\Controllers\IndeedApplyController' # Update the url_segment to match Webium\IndeedApply\Controllers\IndeedApplyController: url_segment: 'jobs/apply'
Important: Don't forget to update your Indeed Apply postUrl in your job feed to match the new endpoint:
https://yourdomain.com/jobs/apply
Run /dev/build?flush=1 after changing the route.
Authentication
The module supports HMAC-SHA1 signature verification for authenticating Indeed Apply POST requests.
Configuration
Add the following to your project's .env file:
# Indeed Apply Module Configuration INDEED_APPLY_API_SECRET="your-api-secret-here" INDEED_APPLY_REQUIRE_SIGNATURE="false"
Environment Variables:
INDEED_APPLY_API_SECRET- Your shared API secret from Indeed Apply integration settingsINDEED_APPLY_REQUIRE_SIGNATURE- Set to"true"to require valid signatures (recommended for production)
The controller reads these environment variables directly using Environment::getEnv().
How it works
- Indeed Apply sends a POST request with an
x-indeed-signatureheader - The signature is generated using HMAC-SHA1 on the raw JSON body with your shared API secret
- The module verifies the signature matches the expected value
- All requests are logged with signature validation status in
IndeedApplyLog
Security Options
Development mode (default):
INDEED_APPLY_REQUIRE_SIGNATURE="false"
- All requests are accepted regardless of signature
- Signature validation status is logged for debugging
- Use this for initial testing
Production mode (recommended):
INDEED_APPLY_REQUIRE_SIGNATURE="true"
- Only requests with valid signatures are accepted
- Invalid signatures return HTTP 401 Unauthorized
- Protects against unauthorized POST requests
Getting Your API Secret
- Log in to your Indeed Employer account
- Go to Indeed Apply integration settings
- Find the "Shared API Secret" with credential type "Indeed Apply"
- Copy the secret and add it to your configuration
XML Feed Configuration
Add the following field to your Indeed XML feed:
<indeed-apply-data><![CDATA[indeed-apply-apiToken=YOUR_API_TOKEN&indeed-apply-jobTitle=JOB_TITLE&indeed-apply-jobId=JOB_ID&indeed-apply-jobCompanyName=COMPANY_NAME&indeed-apply-jobLocation=LOCATION&indeed-apply-jobUrl=https%3A%2F%2Fyourdomain.com%2Fjob-url&indeed-apply-postUrl=https%3A%2F%2Fyourdomain.com%2Findeed-apply%2F]]></indeed-apply-data>
Note: The indeed-apply-postUrl must point to your domain's /indeed-apply/ endpoint
Expected Data
The module expects the following fields from Indeed:
Job Information
jobTitle- Job titlejobId- Job/vacancy IDjobCompanyName- Company namejobLocation- LocationjobUrl- URL to job posting
Candidate Information
fullName- Full namefirstName- First namelastName- Last nameemail- Email addressphoneNumber- Phone numbercoverLetter- Cover letterresume- CV (file upload)
Custom Questions
All fields starting with question_ or customQuestion are automatically stored as JSON.
CMS Interface
After installation, a new menu item appears in the CMS: Indeed Apply
Here you can:
-
Indeed Apply Applications - View and manage applications
- All received applications
- Candidate information
- CV downloads
- Track status (processed/not processed)
- Add notes
-
Indeed Apply Logs - View request logs
- All received requests
- Request headers and body
- Response codes
- Error messages
- Logs are read-only
Permissions
The module uses the following permission:
CMS_ACCESS_IndeedApplyAdmin- Access to Indeed Apply administration
This can be assigned to user groups via Security > Groups.
Processing Applications
Applications are stored with IsProcessed = false. You can later:
- Manually process them in the CMS
- Automatically process them via a custom script
- Export to Excel for bulk processing
Debugging
All requests are logged in IndeedApplyLog. Here you can see:
- When a request came in
- What the request body was
- Signature validation status (true/false)
- Whether it was successful
- Any error messages
The SignatureValid field in logs shows whether the HMAC-SHA1 signature was valid for each request.
Technical Details
- Namespace:
Webium\IndeedApply - Endpoint URL:
/indeed-apply - Accepted methods: POST only
- CSRF Protection: Disabled for this endpoint (required for external POST requests)
- File uploads: Max 5MB, allowed extensions: pdf, doc, docx, txt, rtf
Resume File Security
Resume files are uploaded to Uploads/IndeedApply/Resumes/ and are automatically protected. Each uploaded resume has CanViewType set to LoggedInUsers, ensuring that only logged-in CMS users can access the files.
Troubleshooting
"Method Not Allowed" error
Check if Indeed is actually sending POST requests to the endpoint.
Applications not being saved
- Check the logs in
Indeed Apply Logsin the CMS - Look at the
RequestBodyto see what data Indeed is sending - Verify that field names match
CVs not uploading
- Check file upload settings in
php.ini - Verify that the
Uploads/IndeedApply/Resumesdirectory has write permissions - Check logs for specific error messages
Invalid signature errors (HTTP 401)
- Verify your
INDEED_APPLY_API_SECRETin.envmatches the shared secret in your Indeed Apply integration settings - Check the
SignatureValidfield inIndeedApplyLogto see signature validation status - Ensure
INDEED_APPLY_REQUIRE_SIGNATUREis set to"false"during initial testing - Confirm the
X-Indeed-Signatureheader is being sent by Indeed
Requirements
- SilverStripe 4.x or 5.x
Documentation
For more information about Indeed Apply, see: https://docs.indeed.com/indeed-apply/add-indeed-apply
License
MIT
Maintainer
Webium - https://webium.nl