---
title: "Configuring a Service Provider"
space: "eInvoicing"
url: "https://www.prilk.com/docs/edocument/integration/service-provider"
updated: "2026-05-14"
---

## Configuring a Service Provider

Once credentials are in place ([Setting Up a Provider](/docs/edocument/integration/getting-started)), you choose how documents flow in and out: webhook for real-time inbound, polling for scheduled pull, or both.

### Webhook (inbound, real-time)

A webhook lets your service provider notify your ERPNext as soon as a document arrives — typically within seconds.

**1. Configure the webhook URL in your provider's dashboard:**

```
https://your-domain.com/api/method/edocument_integration.api.webhook
```

The webhook accepts:
- **Method**: POST
- **Body**: raw PEPPOL UBL XML
- **Authentication**: public (no auth header required — the endpoint is `allow_guest`)

**2. What happens on receipt:**
1. EDocument record created
2. XML attached as a file
3. Profile auto-detected from the XML namespace (CustomizationID)
4. Company auto-detected from the buyer's EndpointID
5. Validation runs

Response back to the provider:
```json
{ "status": "success", "result": { "edocument": "EDOC-00001" } }
```

**3. Security considerations**

Because the endpoint is public, anyone with the URL can POST XML to it. In practice this is acceptable because:
- The XML is validated against XSD + Schematron — junk doesn't survive
- The buyer's EndpointID must match a Company on your site
- Failed validation creates an EDocument with "Validation Failed" status, which a System Manager can review

If you want to harden further:
- Put a WAF rule on the URL that only allows your provider's IP ranges
- Add a shared-secret header check in a `before_insert` hook on EDocument

### Polling (inbound, scheduled)

If your provider doesn't support webhooks (or you prefer pull semantics), polling fetches the inbox periodically.

**Automatic polling**: The app installs a daily scheduled task that polls all active Integration Settings with the Recommand integrator. See `scheduler_events` in `edocument_integration/hooks.py`.

**Manual polling**: On the **EDocument Integration Settings** form, click **Poll Incoming Documents**. The app:
1. Calls the provider's inbox endpoint
2. For each unread document: checks if `EDocument.reference` already exists (duplicate skip), creates an EDocument record, attaches the XML, validates
3. Returns a count: "Processed 2 invoice(s)" or "Skipped 1 duplicate(s)"

### Duplicate prevention
Both inbound paths set `EDocument.reference` to the provider's document ID. If a re-poll or a webhook retry would re-import the same document, the duplicate check kicks in:

```python
existing = frappe.db.exists("EDocument", {"reference": document_id})
if existing:
    return {"skipped": True, "reason": "duplicate"}
```

Skipped duplicates are logged to **Error Log** with the document ID so you have an audit trail.

### Outbound — API method

For outbound, there's nothing to configure beyond credentials. The transmission happens when you click **Transmit via API** on an EDocument. See [Sending & Receiving](/docs/edocument/integration/send-receive).

### Troubleshooting

| Symptom | Where to look |
|---|---|
| Webhook not firing | Provider dashboard logs — confirm URL is correct, payload is well-formed XML |
| Webhook returns 500 | **Error Log** in ERPNext — full traceback |
| Polling pulls nothing | Integration Settings: verify credentials with **Test Connection** if available; check API key hasn't been rotated |
| Transmission succeeds but recipient never gets it | Provider tracking dashboard — the document may be queued at the receiver's Access Point |
| Duplicate documents | Check that `reference` is being set; an old EDocument without `reference` won't trigger the dedup check |
