Send Adobe Sign offer letters when Greenhouse offers get approved

Every couple of hours, catch newly approved Greenhouse offers, pick the right Adobe Acrobat Sign template, send it out for signature, and ping the recruiter.

Agentic Task
Adobe Acrobat SignGreenhouseSlack BotHR & PeopleOperationsOnboarding AutomationNotifications & Alerts
PromptCreate

Every two hours during business hours, sweep Greenhouse for offers that have just moved into the Approved state, send each one out for signature via Adobe Acrobat Sign, log the send back on the Greenhouse candidate, and DM the recruiter on Slack. Be strict about idempotency: never send the same offer twice.

Trigger: cron, every two hours between 08:00 and 20:00 in the account's business timezone (make the timezone and window a workflow setting). On each run, use List Offers on Greenhouse with a created_after (or updated_after) filter based on the last successful run cursor. For each returned offer, call Get Offer to get the full offer (title, starts_at, salary, custom fields, application id, sent_at, resolved_at, status). Only proceed when status is 'approved'. Ignore anything already in 'sent' or 'accepted' or 'deprecated'.

For each approved offer, call Get Candidate on Greenhouse to pull the candidate's full name, primary email address, applications, and the recruiter owner. From the offer's job, resolve the department and office (Greenhouse returns these on the job embedded in the offer, or via List Departments and List Offices if you need the parent department or the office's country). Also call Get User on Greenhouse to resolve the recruiter's email address for the Slack lookup.

Idempotency guard: before doing anything with Adobe Sign, call Get Candidate Activity Feed on the candidate and look for a note this workflow previously wrote for this offer (match on the offer id embedded in the note body — see the note format below). If a matching note exists, skip the offer entirely. This is the only source of truth for whether a letter already went out; do not rely on the offer's own status.

Template selection is a judgement call. The workflow has a configured mapping from (department, office country) to an Adobe Sign library document id, plus an 'optional clauses' rule set (e.g. add a relocation clause when the office country differs from the candidate's current country, add a sign-on bonus clause when a specific custom field is populated). Pick the template that best fits the offer's department and office country. If no mapping exists for that combination, do NOT guess — skip the send and DM the recruiter saying a template mapping is missing for that department + office.

Send the letter via Adobe Acrobat Sign's Create Agreement operation. Reference the chosen library document by id in fileInfos, set state to IN_PROCESS so it sends immediately, and set the participant set to the candidate's email as the sole signer with order 1. Pre-fill mergeFieldInfo for candidate full name, candidate email, job title (from the offer), start date (starts_at, formatted as a human date), salary (formatted with currency and pay period from the offer's compensation object), and hiring manager name (from the job's hiring team). Give the agreement a name like '<Candidate Name> — Offer Letter — <Job Title>'. Handle edge cases where a required custom field is empty by pausing the offer and DMing the recruiter with the missing field name, instead of sending a half-filled letter.

After Adobe Sign returns the agreement id, call Add Candidate Note on the Greenhouse candidate. The note body must contain the phrase 'Offer letter sent via Adobe Sign', the offer id, the Adobe Sign agreement id, and an ISO-8601 UTC timestamp. This exact format is what the idempotency check on the next run will grep for, so keep it stable. Use the recruiter's Greenhouse user id in the On-Behalf-Of header so the note attribution looks right.

Finally, notify the recruiter on Slack Bot. Use Look Up User by Email against the recruiter's email, then Open a Conversation to get a DM channel id, then Send a Message with a short summary: candidate name, role, start date, salary line, agreement id, and a link to the candidate in Greenhouse. If the recruiter isn't in Slack (email not found), post nothing rather than falling back to a channel — surface it as a workflow-level warning so the ops team can fix the mapping.

Error handling: never re-send if any step after Create Agreement fails — the note-write and Slack DM are both retriable, but the agreement send is not. If Create Agreement fails, do not write a note, and surface the failure with the offer id so a human can look. Honor Adobe Sign's Retry-After on 429s and Greenhouse's Retry-After on 429s. Do not retry 4xx errors other than 429 on either side.

Reference on why offer letters are a canonical Adobe Sign use case: https://helpx.adobe.com/sign/integrations/supported-e-sign-workflows.html

Additional information

What does this prompt do?
  • Sweeps Greenhouse a few times a day for offers freshly moved into the Approved state.
  • Picks the right Adobe Acrobat Sign library template based on the role's department and the office country.
  • Sends the letter for signature with the candidate's name, title, salary, start date, and hiring manager pre-filled.
  • Logs the send back on the Greenhouse candidate profile and DMs the recruiter on Slack so the handoff is visible.
What do I need to use this?
  • A Greenhouse account with permission to read offers and candidates and post notes on candidate profiles.
  • An Adobe Acrobat Sign account with your offer letter templates already saved to the library.
  • A Slack workspace where the recruiter listed on the Greenhouse offer can be reached by email.
How can I customize it?
  • How often to sweep, and which hours count as business hours (every hour, every two, weekdays only).
  • Which Adobe Sign library template maps to which department and office combination, and any optional clauses (relocation, sign-on bonus) that apply.
  • Who gets the Slack ping when the letter goes out (the recruiter owner, a shared talent-ops channel, or both).

Frequently asked questions

Will duplicate offer letters go out if the workflow runs twice?
No. Before sending, the workflow reads the candidate's notes and skips the offer if it already logged a send for it. The candidate note is the source of truth for idempotency.
What happens if we don't have a template for a specific department or office yet?
The workflow pauses on that offer, does not send anything, and DMs the recruiter to say a template mapping is missing. That way you never send the wrong letter.
Can we edit the salary or start date before the letter goes out?
Yes. The workflow always uses what's on the Greenhouse offer at the moment it sweeps, so update the offer in Greenhouse first and the next run will pick up your changes.
Does this replace our offer approval process?
No. A human still approves the offer in Greenhouse. The workflow only fires once the offer is in the Approved state.
What if a custom field the template needs is empty on the offer?
The workflow flags the offer, skips the send, and pings the recruiter with a note about which field to fill in. You fix it in Greenhouse and the next sweep sends the letter.

Stop copy-pasting offer letters.

Let approved Greenhouse offers turn into signed Adobe Sign letters on their own, with the recruiter looped in on Slack.