The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Mobile Inbox",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "mobile/inbox",
"responseMode": "responseNode",
"options": {}
},
"id": "7f4cd9f2-4d44-4c6f-bcb2-4adf00aa0081",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-1080,
160
]
},
{
"parameters": {
"jsCode": "const headers = $json.headers ?? {};\nconst body = $json.body ?? {};\n\nconst getHeader = (name) => {\n const lower = name.toLowerCase();\n return headers[lower] ?? headers[name] ?? headers[name.toUpperCase()] ?? '';\n};\n\nconst headerSecret = getHeader('x-mobile-secret');\nconst expectedSecret = $env.MOBILE_WEBHOOK_SECRET ?? '';\nconst authorized = Boolean(expectedSecret) && headerSecret === expectedSecret;\n\nconst contentType = String(getHeader('content-type') || '').toLowerCase();\nconst isJsonContentType = contentType.includes('application/json');\n\nconst payloadIsObject = body && typeof body === 'object' && !Array.isArray(body);\nconst rawText = payloadIsObject && typeof body.text === 'string' ? body.text : '';\nconst rawUrl = payloadIsObject && typeof body.url === 'string' ? body.url : '';\nlet rawTags = payloadIsObject ? body.tags : [];\nif (typeof rawTags === 'string') {\n rawTags = rawTags.split(',').map((t) => t.trim()).filter(Boolean);\n}\nif (!Array.isArray(rawTags)) {\n rawTags = [];\n}\nconst tags = rawTags\n .map((tag) => (typeof tag === 'string' ? tag.trim() : String(tag ?? '').trim()))\n .filter(Boolean);\n\nconst source = payloadIsObject && typeof body.source === 'string' && body.source.trim()\n ? body.source.trim()\n : 'ios-shortcut';\n\nconst metaInput = payloadIsObject && body.meta && typeof body.meta === 'object' && !Array.isArray(body.meta)\n ? body.meta\n : {};\n\nconst normalized = {\n text: rawText.trim(),\n url: rawUrl.trim(),\n tags,\n source,\n meta: {\n sentAt: typeof metaInput.sentAt === 'string' && metaInput.sentAt.trim() ? metaInput.sentAt : null,\n device: typeof metaInput.device === 'string' && metaInput.device.trim() ? metaInput.device : null\n }\n};\n\nconst hasMeaningfulPayload = Boolean(normalized.text || normalized.url || normalized.tags.length > 0);\n\nreturn [{\n json: {\n authorized,\n isJsonContentType,\n payloadValid: payloadIsObject && hasMeaningfulPayload,\n normalized,\n receivedAt: new Date().toISOString()\n }\n}];"
},
"id": "5f7656f4-95d4-4a34-b454-4e71f8f8a6e1",
"name": "Validate and Normalize",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-860,
160
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.authorized }}",
"value2": true
}
]
},
"options": {}
},
"id": "e31b1315-273c-4d68-95e7-a95f504e6367",
"name": "IF Authorized",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-640,
160
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ { ok: false, error: 'unauthorized' } }}",
"options": {
"responseCode": 401
}
},
"id": "4f4cfbc1-a83e-4a25-a124-57018d2edea3",
"name": "Respond 401",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
-420,
320
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.isJsonContentType }}",
"value2": true
}
]
},
"options": {}
},
"id": "753cfbec-7983-4e9c-b7db-c63a53b01374",
"name": "IF JSON Content-Type",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-420,
80
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ { ok: false, error: 'unsupported_media_type', expected: 'application/json' } }}",
"options": {
"responseCode": 415
}
},
"id": "e8c5ca6f-c255-43be-a4f8-882bc9d0fe25",
"name": "Respond 415",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
-200,
220
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.payloadValid }}",
"value2": true
}
]
},
"options": {}
},
"id": "4be14a99-44f3-4f80-a3a5-279bf18ef3bb",
"name": "IF Payload Valid",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-200,
80
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ { ok: false, error: 'invalid_payload', message: 'Provide at least one of text, url, or tags.' } }}",
"options": {
"responseCode": 400
}
},
"id": "9af0d174-3440-4d6f-9925-081ac3a33ceb",
"name": "Respond 400",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
20,
220
]
},
{
"parameters": {
"jsCode": "const data = $getWorkflowStaticData('global');\nif (!Array.isArray(data.mobileInboxLog)) data.mobileInboxLog = [];\n\nconst entry = {\n receivedAt: $json.receivedAt,\n text: $json.normalized.text,\n url: $json.normalized.url,\n tags: $json.normalized.tags,\n source: $json.normalized.source,\n meta: $json.normalized.meta\n};\n\ndata.mobileInboxLog.push(entry);\nif (data.mobileInboxLog.length > 200) {\n data.mobileInboxLog = data.mobileInboxLog.slice(-200);\n}\n\nreturn [{\n json: {\n ok: true,\n receivedAt: $json.receivedAt,\n echo: {\n text: entry.text,\n url: entry.url,\n tags: entry.tags,\n source: entry.source\n }\n }\n}];"
},
"id": "521f2f98-d86d-4fca-9a98-f8f2476294fb",
"name": "Log Inbox Entry",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
20,
80
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 200
}
},
"id": "d6bc3b18-5d3e-4a70-9f0c-7f6f388c4213",
"name": "Respond 200",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
240,
80
]
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Validate and Normalize",
"type": "main",
"index": 0
}
]
]
},
"Validate and Normalize": {
"main": [
[
{
"node": "IF Authorized",
"type": "main",
"index": 0
}
]
]
},
"IF Authorized": {
"main": [
[
{
"node": "IF JSON Content-Type",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond 401",
"type": "main",
"index": 0
}
]
]
},
"IF JSON Content-Type": {
"main": [
[
{
"node": "IF Payload Valid",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond 415",
"type": "main",
"index": 0
}
]
]
},
"IF Payload Valid": {
"main": [
[
{
"node": "Log Inbox Entry",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond 400",
"type": "main",
"index": 0
}
]
]
},
"Log Inbox Entry": {
"main": [
[
{
"node": "Respond 200",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Mobile Inbox. Webhook trigger; 10 nodes.
Source: https://github.com/organized-thot/codex-n8n/blob/32d7a076da3a990f6686c6fcb9cf1292482ee7b6/workflows/mobile-inbox.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A production-ready authentication workflow implementing secure user registration, login, token verification, and refresh token mechanisms. Perfect for adding authentication to any application without
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
This n8n template demonstrates how a simple Multi-Layer Perceptron (MLP) neural network can predict housing prices. The prediction is based on four key features, processed through a three-layer model.
github code Try yourself
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.