Managing Resources

Publishers

Manage traffic sources and lead vendors — publisher CRUD, pause/resume ingestion, volume caps and quality thresholds, per-publisher pricing, and delivery statistics.

A publisher is a source of inbound items — a traffic source or lead vendor that submits Work into Ductor. It is the supply-side counterpart to a recipient: a recipient is a Worker a routing decision selects, while a publisher is an origin that feeds work in. Managing a publisher means controlling how much it may submit, the quality bar its submissions must clear, what you pay for accepted items, and whether it is currently allowed to submit at all — the entry gate where work is admitted before it is priced and routed.

Where it lives

Publishers are served by PublishersService under /api/publishers; the service implementation is in modules/services/publisher/. Every operation is tenant-scoped and gated by publisher:read, publisher:write, or publisher:delete.

The publisher object

Prop

Type

The current_* counters are read-only usage against the matching *_cap. Caps and the quality threshold are the two levers that shape ingestion: a cap bounds how much a publisher may send, the threshold bounds what quality is accepted.

Create and configure

CreatePublisherPOST /api/publishers (publisher:write) — registers a source with its caps, quality bar, and revenue share. Only name is required; caps default to 0 (unlimited).

curl -s -X POST https://api.ductor.io/api/publishers \
  -H "Authorization: Bearer $DUCTOR_TOKEN" \
  -H "X-Tenant-ID: $DUCTOR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Lead Source",
    "daily_cap": 1000,
    "weekly_cap": 5000,
    "monthly_cap": 20000,
    "quality_threshold": 0.7,
    "revenue_share": 15.0,
    "tags": ["north-america", "tier1"]
  }'

A duplicate name returns a conflict; an out-of-range quality threshold or other business-rule violation returns an unprocessable-entity error rather than being silently clamped.

GetPublisher (GET /api/publishers/{publisher_id}, publisher:read) returns one publisher including its live usage counters; ListPublishers (GET /api/publishers, publisher:read) paginates the tenant's publishers newest-first with pagination.page_size (max 1000, default 50) and pagination.page_token. UpdatePublisher (PUT /api/publishers/{publisher_id}, publisher:write) edits name, caps, threshold, revenue share, and tags.

DeletePublisher (DELETE /api/publishers/{publisher_id}, publisher:delete) permanently removes a publisher. Items it has already submitted are not affected.

Pause and resume ingestion

Rather than deleting a misbehaving source, pause it. PausePublisherPOST /api/publishers/{publisher_id}/pause (publisher:write) — stops the publisher from accepting new routable items; items already in flight are unaffected. ResumePublisher (POST .../resume, publisher:write) re-enables it.

curl -s -X POST https://api.ductor.io/api/publishers/$PUBLISHER_ID/pause \
  -H "Authorization: Bearer $DUCTOR_TOKEN" \
  -H "X-Tenant-ID: $DUCTOR_TENANT_ID"

Pause and resume are guarded against no-ops: pausing an already-paused publisher (or resuming one that isn't paused) returns an unprocessable-entity error, so the status transition is always explicit.

Pricing

Each publisher carries its own monetization settings for accepted items. GetPublisherPricing (GET /api/publishers/{publisher_id}/pricing, publisher:read) returns the current configuration; UpdatePublisherPricing (PUT .../pricing, publisher:write) upserts it.

Prop

Type

curl -s -X PUT https://api.ductor.io/api/publishers/$PUBLISHER_ID/pricing \
  -H "Authorization: Bearer $DUCTOR_TOKEN" \
  -H "X-Tenant-ID: $DUCTOR_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{ "publisher_id": "'"$PUBLISHER_ID"'", "price_per_accepted_lead": 55.0, "currency": "USD" }'

Statistics

GetPublisherStatsGET /api/publishers/{publisher_id}/stats (publisher:read) — returns volume and quality metrics for a publisher: how much it submitted, how much was accepted or rejected, its acceptance rate, average quality, and the revenue it generated.

Prop

Type

Read acceptance_rate and average_quality together against the publisher's quality_threshold to decide whether a source is worth its caps and revenue share, or whether to tighten the threshold, pause it, or retire it.

Operations at a glance

OperationMethod & pathScope
List publishersGET /api/publisherspublisher:read
Create publisherPOST /api/publisherspublisher:write
Get publisherGET /api/publishers/{publisher_id}publisher:read
Update publisherPUT /api/publishers/{publisher_id}publisher:write
Delete publisherDELETE /api/publishers/{publisher_id}publisher:delete
Pause publisherPOST /api/publishers/{publisher_id}/pausepublisher:write
Resume publisherPOST /api/publishers/{publisher_id}/resumepublisher:write
Get pricingGET /api/publishers/{publisher_id}/pricingpublisher:read
Update pricingPUT /api/publishers/{publisher_id}/pricingpublisher:write
Get statisticsGET /api/publishers/{publisher_id}/statspublisher:read

Where to go next