Complete Client Onboarding Automation for Freelancers with n8n
Why This Automation Matters
As a freelancer, client onboarding can be time-consuming and repetitive. This workflow automates the entire process from initial client inquiry to project kickoff, saving you 3-5 hours per client while ensuring consistency and professionalism.
Benefits:
- Automatically generate and send contracts based on client requirements
- Collect payments and deposits seamlessly
- Set up project management boards and communication channels
- Send welcome emails and project timelines
- Track client progress through your CRM
- Reduce manual data entry and human errors
What You Need Before Starting
Required Accounts & Tools:
- n8n Cloud or self-hosted instance
- Google Workspace (Drive, Docs, Sheets)
- Stripe or PayPal for payments
- Slack or Discord for client communication
- Trello, Notion, or Airtable for project management
- Mailgun or SendGrid for email automation
Credentials to Set Up:
- Google Service Account with API access
- Stripe API keys
- Email service API credentials
- Project management tool API access
- Communication platform webhooks
Templates to Prepare:
- Contract template in Google Docs with merge fields
- Welcome email template
- Project timeline template
- Invoice template
Complete Node-by-Node Build Instructions
1. Webhook Trigger Node
- Add a Webhook node as your starting trigger
- Set HTTP Method to
POST - Configure path as
/client-onboarding - Set Response Mode to “Respond Immediately”
- Authentication: None (or add basic auth for security)
2. Extract Client Data Node
- Add a Set node after the webhook
- Name it “Extract Client Data”
- Configure these fields:
client_name:{{ $json.body.client_name }}client_email:{{ $json.body.client_email }}project_type:{{ $json.body.project_type }}budget:{{ $json.body.budget }}timeline:{{ $json.body.timeline }}client_id:{{ $json.body.client_id || 'CLT_' + new Date().getTime() }}
3. Create CRM Entry Node
- Add Google Sheets node
- Operation: “Append”
- Connect to your client database spreadsheet
- Map extracted data to appropriate columns
- Include timestamp:
{{ new Date().toISOString() }}
4. Generate Contract Node
- Add Google Docs node
- Operation: “Create Document from Template”
- Select your contract template
- Replace placeholders:
{{CLIENT_NAME}}with{{ $('Extract Client Data').item.json.client_name }}{{PROJECT_TYPE}}with{{ $('Extract Client Data').item.json.project_type }}{{BUDGET}}with{{ $('Extract Client Data').item.json.budget }}{{TIMELINE}}with{{ $('Extract Client Data').item.json.timeline }}
5. Set Contract Permissions Node
- Add Google Drive node
- Operation: “Update Permissions”
- File ID:
{{ $('Generate Contract').item.json.id }} - Grant view access to client email
- Set sharing link to “Anyone with link can view”
6. Create Payment Link Node
- Add Stripe or PayPal node
- Operation: “Create Payment Link”
- Amount:
{{ $('Extract Client Data').item.json.budget * 0.5 }}(50% deposit) - Description:
Deposit for {{ $('Extract Client Data').item.json.project_type }} project - Success URL: Your project kickoff page
- Cancel URL: Your payment retry page
7. Set Up Project Board Node
- Add Trello or Notion node
- Operation: “Create Board” or “Create Page”
- Board/Page name:
{{ $('Extract Client Data').item.json.client_name }} - {{ $('Extract Client Data').item.json.project_type }} - Add standard lists/sections:
- To Do
- In Progress
- Client Review
- Completed
8. Create Communication Channel Node
- Add Slack node
- Operation: “Create Channel”
- Channel name:
client-{{ $('Extract Client Data').item.json.client_id.toLowerCase() }} - Make private
- Invite yourself and relevant team members
9. Send Welcome Email Node
- Add Email node (Mailgun/SendGrid)
- To:
{{ $('Extract Client Data').item.json.client_email }} - Subject:
Welcome! Next steps for your {{ $('Extract Client Data').item.json.project_type }} project - Body template:
Hi {{ $('Extract Client Data').item.json.client_name }},
Welcome aboard! I'm excited to work on your {{ $('Extract Client Data').item.json.project_type }} project.
Next steps:
1. Review and sign your contract: {{ $('Generate Contract').item.json.webViewLink }}
2. Complete your deposit payment: {{ $('Create Payment Link').item.json.url }}
3. Join our project channel: {{ $('Create Communication Channel').item.json.channel.name }}
Once payment is received, we'll schedule our kickoff call and begin work immediately.
Best regards,
[Your Name]
10. Wait for Payment Node
- Add Wait node
- Resume On: “Webhook call”
- Webhook path:
/payment-received - Timeout: 7 days
11. Update Client Status Node
- Add Google Sheets node
- Operation: “Update”
- Find row by client_id
- Update status to “Payment Received”
- Add payment date timestamp
12. Schedule Kickoff Call Node
- Add Calendly or Google Calendar node
- Operation: “Create Event”
- Title:
Kickoff Call - {{ $('Extract Client Data').item.json.client_name }} - Attendees: Your email and client email
- Duration: 60 minutes
- Send calendar invite
13. Send Kickoff Email Node
- Add Email node
- To: Client email
- Subject:
Project kickoff scheduled - Let's get started! - Include calendar invite and project board link
14. Error Handling Node
- Add If node after each critical step
- Check for successful responses
- Route errors to Slack notification node
- Send error details to your monitoring channel
Full Workflow JSON Code
{
"meta": {
"instanceId": "your-instance-id"
},
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "client-onboarding",
"responseMode": "respondImmediately"
},
"id": "webhook-trigger",
"name": "Client Onboarding Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [240, 300]
},
{
"parameters": {
"values": {
"string": [
{
"name": "client_name",
"value": "={{ $json.body.client_name }}"
},
{
"name": "client_email",
"value": "={{ $json.body.client_email }}"
},
{
"name": "project_type",
"value": "={{ $json.body.project_type }}"
},
{
"name": "budget",
"value": "={{ $json.body.budget }}"
},
{
"name": "timeline",
"value": "={{ $json.body.timeline }}"
},
{
"name": "client_id",
"value": "={{ $json.body.client_id || 'CLT_' + new Date().getTime() }}"
}
]
}
},
"id": "extract-data",
"name": "Extract Client Data",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [460, 300]
},
{
"parameters": {
"operation": "append",
"documentId": "your-google-sheet-id",
"sheetName": "Clients",
"columns": {
"mappingMode": "defineBelow",
"value": {
"client_id": "={{ $('Extract Client Data').item.json.client_id }}",
"client_name": "={{ $('Extract Client Data').item.json.client_name }}",
"client_email": "={{ $('Extract Client Data').item.json.client_email }}",
"project_type": "={{ $('Extract Client Data').item.json.project_type }}",
"budget": "={{ $('Extract Client Data').item.json.budget }}",
"timeline": "={{ $('Extract Client Data').item.json.timeline }}",
"status": "Contract Sent",
"created_date": "={{ new Date().toISOString() }}"
}
}
},
"id": "create-crm-entry",
"name": "Create CRM Entry",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 3,
"position": [680, 180]
},
{
"parameters": {
"operation": "createFromTemplate",
"templateId": "your-contract-template-id",
"title": "Contract - {{ $('Extract Client Data').item.json.client_name }}",
"replacements": [
{
"find": "{{CLIENT_NAME}}",
"replace": "={{ $('Extract Client Data').item.json.client_name }}"
},
{
"find": "{{PROJECT_TYPE}}",
"replace": "={{ $('Extract Client Data').item.json.project_type }}"
},
{
"find": "{{BUDGET}}",
"replace": "={{ $('Extract Client Data').item.json.budget }}"
},
{
"find": "{{TIMELINE}}",
"replace": "={{ $('Extract Client Data').item.json.timeline }}"
}
]
},
"id": "generate-contract",
"name": "Generate Contract",
"type": "n8n-nodes-base.googleDocs",
"typeVersion": 1,
"position": [680, 300]
},
{
"parameters": {
"operation": "share",
"fileId": "={{ $('Generate Contract').item.json.documentId }}",
"permissions": {
"role": "reader",
"type": "user",
"emailAddress": "={{ $('Extract Client Data').item.json.client_email }}"
}
},
"id": "share-contract",
"name": "Share Contract",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [680, 420]
},
{
"parameters": {
"resource": "price",
"operation": "create",
"productId": "your-product-id",
"unitAmount": "={{ Math.round($('Extract Client Data').item.json.budget * 50) }}",
"currency": "usd",
"recurring": false
},
"id": "create-payment",
"name": "