Send Adobe Sign offer letters when Greenhouse offers get approved

By General Input

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.

Integrations

  • Adobe Acrobat Sign
  • Greenhouse
  • Slack Bot

Type

Agentic Task

Categories

  • HR & People
  • Operations

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

Related prompts

Explore more prompts
A brand asset library your marketing team actually searchesTurn Mailjet email clicks into ranked HubSpot follow-upsClean out the Looker dashboards and Looks nobody opensLiveKit live operations console for room moderationWake up dormant Keap leads with a researched reasonLiveChat coverage board for planning next week's shiftsPhone routing control panel for LiveKit voice agentsLinkedIn Ads budget pacing dashboard for every client accountGive your team Looker numbers without buying more seatsPause marketing emails to escalated customers, then restore them