Connect an application
Use a CopyLoop webhook to create or update contacts from your web or mobile application. Common uses include account signups, registrations, lead capture, profile updates, and contact imports.
This is the current supported application-integration path. See Choose an integration before deciding which data belongs in the payload.
The webhook accepts contact and profile data. It is not a general product-activity endpoint, so do
not send events such as trial_started, feature_used, or subscription_cancelled through it.
The webhook URL and API key are server secrets. Never include them in browser code, a mobile application, or a public repository.
Set up CopyLoop
Section titled “Set up CopyLoop”Decide which application data is actually useful in CopyLoop. Start with the smallest useful mapping rather than copying every available field.
A general connection might include:
source_record_idfor the stable record ID in the source applicationsource_systemfor the application or workflow that sent the recordsynced_atfor the time the source record was last updated
- In Settings → Fields, create the custom fields you want to receive.
- Create a target contact list, such as Application contacts. Every webhook requires one.
- Open Settings → Webhooks and create a webhook named for the connection, such as Application contact sync.
- Select the target list and add a default tag such as
application-sync. - Map the incoming application fields to the CopyLoop fields:
sourceRecordId→source_record_idsourceSystem→source_systemsyncedAt→synced_at
- Store the generated webhook URL and API key in the application’s server-side secret manager.
email, firstName, and lastName are standard CopyLoop fields and match automatically. Custom
fields must exist before they can be mapped. CopyLoop ignores unknown, unmapped fields.
Send a contact from the backend
Section titled “Send a contact from the backend”Save the record in your application first. Then enqueue the CopyLoop request in a durable background job or transactional outbox. A CopyLoop outage should not prevent the application’s primary action from succeeding.
A Node.js background worker can use the built-in fetch API:
async function deliverContactToCopyLoop(job) { const response = await fetch(process.env.COPYLOOP_WEBHOOK_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.COPYLOOP_WEBHOOK_API_KEY, 'Idempotency-Key': `contact:${job.contact.id}:${job.id}`, }, body: JSON.stringify({ email: job.contact.email, firstName: job.contact.firstName, lastName: job.contact.lastName, sourceRecordId: job.contact.id, sourceSystem: 'customer-app', syncedAt: job.contact.updatedAt, }), });
if (!response.ok) { // Let the job system apply the retry policy described below. throw new Error(`CopyLoop returned HTTP ${response.status}`); }
return response.json();}CopyLoop responds with HTTP 202 Accepted after authenticating and queuing the request:
{ "success": true, "accepted_id": "33333333-3333-4333-8333-333333333333"}The accepted ID is a delivery receipt. Contact processing may still be underway.
Retry safely
Section titled “Retry safely”Your delivery worker should:
- retry network errors, HTTP
429, and HTTP5xxresponses with exponential backoff and jitter - use the same idempotency key and payload every time it retries the same job
- treat HTTP
400,401,404,409, and413as payload or configuration errors that require intervention - store the accepted ID and enough information to diagnose failed jobs
- redact the webhook URL, API key, email address, and request body from ordinary logs
- provide a safe way to replay a failed job
Sending the same idempotency key and payload again returns the original receipt without creating a
duplicate delivery or contact. Sending a different payload with that key returns HTTP 409 Conflict.
Verify the integration
Section titled “Verify the integration”Before enabling production delivery:
- Create one clearly identifiable test record through the real application flow.
- In Settings → Webhooks, open the webhook and confirm the delivery was processed.
- Find the contact in CopyLoop and verify its standard fields, mapped custom fields, tag, and list.
- Replay the same job with the same idempotency key and confirm it does not create a duplicate.
- Exercise one retryable failure in a non-production environment.
Repeat the check whenever you make a meaningful change to the payload or field mapping. Rotate the API key after any accidental disclosure.
Operate the connection
Section titled “Operate the connection”In production, monitor:
- accepted versus failed delivery jobs
- age of the oldest undelivered job
- CopyLoop HTTP status and accepted ID
- mapping or authorization failures that require intervention
- a small reconciliation query between recent source records and CopyLoop
Alert on a growing queue instead of alerting on every retry. The delivery worker should be able to replay a failed job without repeating the application signup or user action.
Example: account signup
Section titled “Example: account signup”An account signup is one use of this contact connection, not a separate webhook type. After saving
the account, enqueue a contact-delivery job using the application’s user ID as sourceRecordId. Add
fields such as signed_up_at or signup_source only when they serve a clear audience, reporting,
or routing purpose.
Consent and audience eligibility
Section titled “Consent and audience eligibility”Keep profile synchronization separate from the instruction to send marketing.
An application account or contact record is not proof of marketing consent. A custom consent-status field can preserve useful context, but it does not subscribe the contact or establish permission to send. Keep the underlying consent evidence in the system responsible for collecting it.
Do not treat the existence of a CopyLoop contact, list membership, or a tag as automatic audience eligibility. If your application serves people in the EU or UK, confirm the applicable lawful basis and notice before activating a marketing audience.