muninn

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 11 Imported by: 0

README

Muninn

Go Reference

Muninn is a Go library for searching French public procurement data through a single, normalized API.

It queries compatible data sources concurrently, merges strong cross-source matches, preserves source provenance, and returns partial results when one source is unavailable. Muninn is a library only: it does not require a database, run a server, or impose a cache.

Features

  • Federated search across BOAMP, BEAUAMP, and DECP
  • One normalized Tender model for notices and awarded contracts
  • Exact DECP filtering across all awarded suppliers by SIRET
  • Capability-aware routing for exact, approximate, and unsupported filters
  • Concurrent provider calls with partial-result reporting
  • Conservative cross-source consolidation with raw source provenance
  • Deterministic sorting and opaque cursor pagination
  • Configurable HTTP clients, timeouts, and retry policies
  • No third-party runtime dependencies

Requirements

Muninn currently targets Go 1.26.

The built-in providers call public remote APIs, so applications should always set an appropriate context deadline and account for upstream availability and rate limits.

Installation

go get github.com/kvitrvn/muninn

Quick start

Create an engine with the providers your application needs, then call Engine.Search:

package main

import (
	"context"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/kvitrvn/muninn"
	"github.com/kvitrvn/muninn/beauamp"
	"github.com/kvitrvn/muninn/boamp"
	"github.com/kvitrvn/muninn/decp"
)

func main() {
	engine := muninn.NewEngine(
		boamp.New(),
		beauamp.New(),
		decp.New(),
	)

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	result, err := engine.Search(ctx, muninn.Query{
		Keywords:  []string{"GED"},
		ObjetOnly: true,
		Statuses:  []muninn.TenderStatus{muninn.StatusOpen},
		Sort:      muninn.Sort{Field: muninn.SortByDeadline},
		PageSize:  25,
	})
	if err != nil {
		log.Fatal(err)
	}

	for _, tender := range result.Items {
		fmt.Printf(
			"[%s] %s — deadline: %s\n",
			strings.Join(tender.ProviderNames(), "+"),
			tender.Objet,
			tender.DateLimiteReponse.Format(time.DateOnly),
		)
	}

	for _, warning := range result.Warnings {
		log.Printf(
			"provider %s (%s): %s",
			warning.Provider,
			warning.Code,
			warning.Message,
		)
	}
}

Search returns an error for an invalid query, a canceled context, an invalid cursor, no compatible provider, or when every attempted provider fails. If at least one provider succeeds, its results are returned even when another provider fails; in that case SearchResult.Partial is true and SearchResult.Warnings explains why.

Choosing providers

Providers can be used together through Engine or directly through their package clients.

Package Data source Best suited for Important limitations
boamp Official BOAMP notices Active notices, response deadlines, departments, and historical award notices Supplier SIREN matching is approximate because legacy winners are identified by name; amount and supplier SIRET filtering are unsupported
beauamp Enriched BOAMP data on data.gouv.fr Structured buyer and supplier names/SIRENs, CPV codes, and indicative amounts Supplier SIRET, department, and deadline filters are unsupported; supplier identity and other enriched fields remain indicative
decp Essential public procurement data (DECP) Published awarded contracts, exact supplier SIRENs/SIRETs, and reference amounts Contains awards rather than active notices; department, deadline, open, and closed filters are unsupported

The engine inspects each provider's Capabilities before searching:

  • providers with exact support are queried normally;
  • approximate support is accepted and reported as a warning;
  • providers that cannot satisfy a required filter are skipped and reported;
  • if no provider can execute the query, Search returns muninn.ErrNoCapableProvider.

Calling a provider directly is stricter. An unsupported criterion returns *muninn.UnsupportedFilterError instead of being ignored. Pagination and sorting belong to Engine and are also rejected by direct provider calls.

Building queries

Query fields are combined with AND. Values within the same slice are combined with OR, except when MatchAll requires every keyword.

Field Description
Keywords Text terms to search for
ObjetOnly Restrict keyword matching to the normalized title/object
MatchAll Require every keyword instead of any keyword
Departements Buyer department codes
PublishedFrom, PublishedTo Inclusive publication date range
DeadlineFrom, DeadlineTo Inclusive response deadline range
CPVCodes CPV prefixes
MontantMin, MontantMax Known contract amount range in euros
BuyerSIREN Exact nine-digit buyer SIREN
SupplierSIREN Nine-digit legal-entity SIREN of any awarded supplier, across its establishments
SupplierSIRET Exact 14-digit SIRET of any awarded supplier
NoticeTypes Competition, award, or correction notices
Statuses Open, closed, or awarded tenders
OpenAt Time used to derive open and closed status; zero means now
Sort Publication date descending by default, or deadline ascending
PageSize Results per page; 50 by default and 200 maximum
Cursor Opaque cursor returned by a previous search
CandidateLimit Maximum records collected per provider; zero uses a safe provider default

Use Query.Validate when you want to reject invalid user input before making a network call:

query := muninn.Query{
	BuyerSIREN:    "200055703",
	SupplierSIREN: "123456789",
	MontantMin:    50_000,
	MontantMax:    250_000,
	PageSize:      50,
}

if err := query.Validate(); err != nil {
	// err is a *muninn.ValidationError
}
Open tenders

StatusOpen is a derived lifecycle state. A tender is open when it is a competition or correction notice, has a known response deadline, has not passed that deadline, and has no known awarded supplier.

For reproducible searches, set Query.OpenAt. When it is zero, the engine uses the current time and stores that value in the pagination cursor.

result, err := muninn.NewEngine(boamp.New()).Search(ctx, muninn.Query{
	Keywords: []string{"electronic archiving"},
	Statuses: []muninn.TenderStatus{muninn.StatusOpen},
	OpenAt:   time.Date(2026, time.July, 28, 0, 0, 0, 0, time.UTC),
	Sort:     muninn.Sort{Field: muninn.SortByDeadline},
})
Pagination

Pass NextCursor back with the same query to fetch the next page:

query := muninn.Query{
	Keywords: []string{"cybersecurity"},
	PageSize: 20,
}

for {
	result, err := engine.Search(ctx, query)
	if err != nil {
		return err
	}

	consume(result.Items)

	if result.NextCursor == "" {
		break
	}
	query.Cursor = result.NextCursor
}

Cursors are tied to the complete query. Changing a filter or sort order while reusing a cursor returns *muninn.ValidationError. A cursor may also become stale if the upstream result set changes between pages.

Working with results

SearchResult contains:

Field Meaning
Items Current page of normalized tenders
Total Consolidated matches before pagination
TotalExact Whether the total is unaffected by warnings or skipped providers
NextCursor Opaque cursor for the next page, or an empty string
Partial Whether warnings affected coverage or precision
Warnings Machine-readable provider warnings

Warnings use stable codes:

  • muninn.WarningProviderError
  • muninn.WarningUnsupportedFilter
  • muninn.WarningApproximateFilter
  • muninn.WarningTruncated

Each Tender keeps all contributing source records:

type SourceReference struct {
	Provider  string
	ID        string
	URL       string
	RawFields map[string]any
}

Use Tender.ProviderNames for display and Tender.Sources when you need the native identifier, source URL, or raw source fields.

Awarded contractors are exposed through Tender.Suppliers. DECP preserves the native titulaire order, accepts SIREN and SIRET identifiers, ignores unrelated identifier schemes, and removes duplicates. BOAMP maps both legacy result notices and eForms winners; when a legacy notice only contains a company name, SupplierSIREN resolves official company names and reports approximate support. Consolidation keeps distinct establishments while using their common SIREN to relate records across sources.

Migration note: Tender.Supplier Buyer was replaced by Tender.Suppliers []Buyer. Callers must iterate the list instead of reading a single awarded contractor.

Muninn merges records only when there is strong cross-source evidence. When evidence is incomplete, it keeps separate tenders rather than risk a false merge.

HTTP and retry configuration

Each built-in provider accepts a custom *http.Client and retry.Policy. Defaults are suitable for basic usage, but production applications will usually want their own transport, observability, and deadlines.

httpClient := &http.Client{
	Timeout: 15 * time.Second,
}
retryPolicy := retry.Policy{
	MaxAttempts: 4,
	BaseDelay:   200 * time.Millisecond,
	MaxDelay:    3 * time.Second,
}

engine := muninn.NewEngine(
	boamp.New(
		boamp.WithHTTPClient(httpClient),
		boamp.WithRetryPolicy(retryPolicy),
	),
	decp.New(
		decp.WithHTTPClient(httpClient),
		decp.WithRetryPolicy(retryPolicy),
	),
	beauamp.New(
		beauamp.WithHTTPClient(httpClient),
		beauamp.WithRetryPolicy(retryPolicy),
	),
)

Retries apply to HTTP 429 responses, HTTP 5xx responses, and transient network errors. Context cancellation and deadlines stop retries immediately. The default policy makes four attempts in total with exponential backoff, full jitter, and a five-second cap.

Provider-specific options include:

  • decp.WithDataset to select another DECP dataset;
  • beauamp.WithResources to pin exact tabular resource IDs;
  • beauamp.WithResourceCacheTTL to control resource-catalog caching;
  • base URL options for tests and controlled upstream proxies.

Error handling

Use errors.Is for sentinel and context errors, and errors.As for structured validation errors:

result, err := engine.Search(ctx, query)
if err != nil {
	var validationErr *muninn.ValidationError

	switch {
	case errors.As(err, &validationErr):
		// Invalid field or cursor.
	case errors.Is(err, muninn.ErrNoProviders):
		// The engine was created without providers.
	case errors.Is(err, muninn.ErrNoCapableProvider):
		// Every provider was incompatible with the query.
	case errors.Is(err, context.Canceled),
		errors.Is(err, context.DeadlineExceeded):
		// The request was canceled or timed out.
	default:
		// Every attempted provider failed.
	}
}

Provider warnings are not returned as error when usable results exist. Check result.Partial and inspect result.Warnings after every successful search if coverage matters to your application.

Implementing a provider

Implement muninn.Provider to add an internal data source or another public API:

type Provider interface {
	Name() string
	Capabilities() muninn.Capabilities
	Search(context.Context, muninn.Query) (muninn.ProviderResult, error)
}

ProviderResult.Total describes matches in that provider before federation. Set TotalExact to describe the source count and Truncated when collection stopped before all matches were fetched.

Provider implementations should:

  • validate the query with muninn.ValidateProviderQuery and Query.Validate;
  • reject unsupported filters with muninn.ValidateCapabilities;
  • honor context cancellation;
  • return normalized Tender values with at least one SourceReference;
  • avoid implementing engine-owned pagination and sorting.

Known limitations

  • BOAMP is authoritative, but some fields extracted from recent eForms payloads remain best effort. Historical supplier-SIREN searches also depend on the official company-search API and name matching, so the engine emits an approximate-filter warning.
  • BEAUAMP data is indicative and its tabular API only supports a subset of the source data and filters.
  • DECP contains awarded contracts, not the complete active-notice lifecycle.
  • Search completeness depends on upstream availability, pagination limits, API rate limits, and schema stability.
  • Muninn does not provide persistence, caching of search results, an HTTP API, or a background index.

Documentation

Development

go test ./...
go test -race ./...
go vet ./...

License

Muninn is distributed under the MIT License.

Documentation

Overview

Package muninn provides a federated Go search engine for French public procurement data.

Providers declare their capabilities and return normalized ProviderResult values. Engine queries compatible providers concurrently, preserves partial results, consolidates strong cross-source matches, applies common lifecycle filters, and returns a deterministic SearchResult page.

The built-in providers live in the boamp, beauamp and decp subpackages. Applications compose only the sources they need:

engine := muninn.NewEngine(boamp.New(), beauamp.New(), decp.New())
result, err := engine.Search(ctx, muninn.Query{
	Keywords:  []string{"GED"},
	ObjetOnly: true,
	PageSize:  25,
})

Tender.Sources preserves the native ID, URL and raw payload of every source contributing to a consolidated record. Muninn deliberately favors missed merges over false merges when cross-source evidence is incomplete.

Index

Examples

Constants

View Source
const (
	// DefaultPageSize is used by Engine when Query.PageSize is zero.
	DefaultPageSize = 50
	// MaxPageSize prevents a caller from accidentally materializing an
	// unbounded response.
	MaxPageSize = 200
)

Variables

View Source
var (
	// ErrNoProviders means Engine was constructed without a source.
	ErrNoProviders = errors.New("muninn: no providers configured")
	// ErrNoCapableProvider means every provider was incompatible with at least
	// one requested filter.
	ErrNoCapableProvider = errors.New("muninn: no provider supports the query")
)

Functions

func ValidateCapabilities

func ValidateCapabilities(q Query, caps Capabilities) error

ValidateCapabilities checks that caps can execute every criterion in q. Approximate support is accepted and discoverable through Capabilities.

func ValidateProviderQuery

func ValidateProviderQuery(q Query) error

ValidateProviderQuery rejects pagination and ordering fields that are owned by Engine. Built-in providers call it so direct usage never ignores them.

Types

type AvisType

type AvisType int

AvisType distinguishes a call-for-competition notice from an award/result notice.

const (
	AvisInconnu AvisType = iota
	AvisAppelConcurrence
	AvisAttribution
	AvisRectificatif
)

func (AvisType) String

func (a AvisType) String() string

type Buyer

type Buyer struct {
	Nom             string
	SIRET           string
	SIREN           string
	Ville           string
	CodeDepartement string
}

Buyer represents an economic actor of a tender: either the public buyer or one of the awarded contractors (titulaires) in Tender.Suppliers.

func (Buyer) SIREN9

func (b Buyer) SIREN9() string

SIREN9 returns the 9-digit SIREN identifying the legal entity, derived from SIREN when set, otherwise from the first 9 digits of SIRET (a SIRET is a SIREN plus a 5-digit establishment number). It returns "" when neither yields a plausible SIREN. This is the stable key used to relate an actor across sources (a buyer or a supplier keeps its SIREN, its SIRET may vary per site).

type Capabilities

type Capabilities map[Filter]SupportLevel

Capabilities declares provider behavior. Missing entries are unsupported.

func (Capabilities) Support

func (c Capabilities) Support(filter Filter) SupportLevel

Support returns the declared support level for a filter.

type EngagementType

type EngagementType int

EngagementType is the contractual engagement type: firm contract or framework agreement (purchase-order based or with subsequent contracts). This is a separate axis from the procedure type, and the two combine.

const (
	EngagementInconnu EngagementType = iota
	EngagementFerme
	EngagementAccordCadreBC // purchase-order framework agreement
	EngagementAccordCadreMS // subsequent-contract framework agreement
)

func (EngagementType) String

func (e EngagementType) String() string

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine federates providers, consolidates their records, applies normalized filters, and returns a deterministic page.

func NewEngine

func NewEngine(providers ...Provider) *Engine

NewEngine constructs a federated search engine.

func (*Engine) Search

func (e *Engine) Search(ctx context.Context, q Query) (SearchResult, error)

Search queries compatible providers concurrently. A provider failure is non-fatal when another provider succeeds; the response is then marked partial and carries a machine-readable warning.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/kvitrvn/muninn"
)

type staticProvider struct {
	name    string
	tenders []muninn.Tender
}

var _ muninn.Provider = staticProvider{}

func (p staticProvider) Name() string { return p.name }

func (p staticProvider) Capabilities() muninn.Capabilities {
	return muninn.Capabilities{
		muninn.FilterTitleKeywords: muninn.Exact,
		muninn.FilterNoticeType:    muninn.Exact,
		muninn.FilterStatusOpen:    muninn.Exact,
	}
}

func (p staticProvider) Search(_ context.Context, _ muninn.Query) (muninn.ProviderResult, error) {
	return muninn.ProviderResult{
		Items:      p.tenders,
		Total:      len(p.tenders),
		TotalExact: true,
	}, nil
}

func main() {
	p := staticProvider{name: "interne", tenders: []muninn.Tender{
		{
			Sources:           []muninn.SourceReference{{Provider: "interne", ID: "1"}},
			Objet:             "Solution GED",
			AvisType:          muninn.AvisAppelConcurrence,
			DatePublication:   time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC),
			DateLimiteReponse: time.Date(2026, 8, 15, 0, 0, 0, 0, time.UTC),
		},
	}}

	result, err := muninn.NewEngine(p).Search(context.Background(), muninn.Query{
		Keywords:  []string{"GED"},
		ObjetOnly: true,
		Statuses:  []muninn.TenderStatus{muninn.StatusOpen},
		OpenAt:    time.Date(2026, 7, 28, 0, 0, 0, 0, time.UTC),
	})
	if err != nil {
		panic(err)
	}
	for _, tender := range result.Items {
		fmt.Printf("%s — %s\n", tender.Objet, tender.StatusAt(time.Date(2026, 7, 28, 0, 0, 0, 0, time.UTC)))
	}
}
Output:
Solution GED — open

type Filter

type Filter string

Filter identifies one independently supportable query feature.

const (
	FilterTitleKeywords Filter = "title_keywords"
	FilterFullText      Filter = "full_text"
	FilterDepartments   Filter = "departments"
	FilterPublication   Filter = "publication_date"
	FilterDeadline      Filter = "deadline"
	FilterCPV           Filter = "cpv"
	FilterAmount        Filter = "amount"
	FilterBuyerSIREN    Filter = "buyer_siren"
	FilterSupplierSIREN Filter = "supplier_siren"
	FilterSupplierSIRET Filter = "supplier_siret"
	FilterNoticeType    Filter = "notice_type"
	FilterStatusOpen    Filter = "status_open"
	FilterStatusClosed  Filter = "status_closed"
	FilterStatusAwarded Filter = "status_awarded"
)

type ProcedureType

type ProcedureType int

ProcedureType is the award procedure type, independent of the engagement type (see EngagementType).

const (
	ProcedureInconnue ProcedureType = iota
	ProcedureOuverte
	ProcedureRestreinte
	ProcedureNegocieeAvecPublicite
	ProcedureNegocieeSansPublicite
	ProcedureDialogueCompetitif
	ProcedureConcours
)

func (ProcedureType) String

func (p ProcedureType) String() string

type Provider

type Provider interface {
	Name() string
	Capabilities() Capabilities
	Search(ctx context.Context, q Query) (ProviderResult, error)
}

Provider is the contract implemented by every procurement source.

type ProviderResult

type ProviderResult struct {
	Items      []Tender
	Total      int
	TotalExact bool
	Truncated  bool
}

ProviderResult is the normalized response produced by one data source. Total describes matches from that provider before cross-source merging.

type Query

type Query struct {
	Keywords []string

	// ObjetOnly restricts keyword matching to the normalized title/object.
	// When false, providers may use their native full-text search.
	ObjetOnly bool
	// MatchAll requires every keyword instead of at least one.
	MatchAll bool

	Departements []string

	PublishedFrom time.Time
	PublishedTo   time.Time
	DeadlineFrom  time.Time
	DeadlineTo    time.Time

	CPVCodes   []string
	MontantMin float64
	MontantMax float64
	BuyerSIREN string
	// SupplierSIREN matches any awarded contractor (titulaire) by its stable
	// 9-digit legal-entity identifier, including establishments with another
	// SIRET.
	SupplierSIREN string
	// SupplierSIRET matches one awarded contractor (titulaire) by its exact
	// 14-digit establishment identifier.
	SupplierSIRET string

	NoticeTypes []AvisType
	Statuses    []TenderStatus

	// OpenAt is the instant used to derive open/closed statuses. Its zero value
	// means "now"; Engine freezes that instant in the pagination cursor.
	OpenAt time.Time

	Sort     Sort
	PageSize int
	Cursor   string

	// CandidateLimit caps how many records each provider may collect before
	// federation. Zero uses the provider's safe default.
	CandidateLimit int
}

Query describes a federated procurement search. Criteria are combined with AND; values inside a slice (departments, CPV codes, notice types, statuses) are combined with OR.

func (Query) Validate

func (q Query) Validate() error

Validate checks query invariants without performing I/O.

type SearchResult

type SearchResult struct {
	Items      []Tender
	Total      int
	TotalExact bool
	NextCursor string
	Partial    bool
	Warnings   []Warning
}

SearchResult is the stable public response returned by Engine.

type Sort

type Sort struct {
	Field     SortField
	Direction SortDirection
}

Sort describes the ordering of a federated result. The zero value means publication date, newest first.

type SortDirection

type SortDirection string

SortDirection controls ascending or descending ordering.

const (
	SortAscending  SortDirection = "asc"
	SortDescending SortDirection = "desc"
)

type SortField

type SortField string

SortField selects the deterministic ordering applied after federation.

const (
	SortByPublication SortField = "publication"
	SortByDeadline    SortField = "deadline"
)

type SourceReference

type SourceReference struct {
	Provider  string
	ID        string
	URL       string
	RawFields map[string]any
}

SourceReference preserves the identity and raw payload of one source that contributed to a normalized Tender.

type SupportLevel

type SupportLevel uint8

SupportLevel describes how reliably a provider can honor a filter.

const (
	Unsupported SupportLevel = iota
	Approximate
	Exact
)

type Tender

type Tender struct {
	Sources []SourceReference

	Titre    string
	Objet    string
	CPVCodes []string
	Buyer    Buyer

	// Suppliers are the awarded contractors (titulaires) when the notice is an
	// award result. An empty list means the contract is not yet awarded or the
	// winners are unknown for this source.
	Suppliers []Buyer

	AvisType   AvisType
	Procedure  ProcedureType
	Engagement EngagementType

	DatePublication   time.Time
	DateLimiteReponse time.Time

	// MontantEstime is the contract amount in euros, 0 when not disclosed. Its
	// authority depends on the source: DECP reports the legally binding awarded
	// amount, BEAUAMP an indicative consolidated value, BOAMP rarely any. When
	// consolidating several sources, prefer the DECP value.
	MontantEstime float64
}

Tender is the normalized representation of a public procurement notice.

func FilterTenders

func FilterTenders(tenders []Tender, q Query, at time.Time) []Tender

FilterTenders applies every criterion that can be checked on the normalized model. Providers still perform native filtering first; this second pass gives federated results consistent semantics.

func MergeTenders

func MergeTenders(tenders []Tender) []Tender

MergeTenders deduplicates records and enriches cross-source matches.

Records from different providers are merged only when buyer SIREN, normalized object and at least one CPV root agree, their publication dates are no more than 180 days apart, and either the winning supplier or a native notice ID agrees. Missing evidence prevents a merge.

func (Tender) DedupKey

func (t Tender) DedupKey() string

DedupKey identifies the record itself, not a speculative cross-source contract match. Cross-source consolidation uses stricter evidence in MergeTenders.

func (Tender) ProviderNames

func (t Tender) ProviderNames() []string

ProviderNames returns the sorted, deduplicated providers contributing to t.

func (Tender) StatusAt

func (t Tender) StatusAt(at time.Time) TenderStatus

StatusAt derives the lifecycle status at at. Deadlines are compared at day granularity because several public datasets expose no response time.

type TenderStatus

type TenderStatus int

TenderStatus is the lifecycle state derived from notice type, response deadline and award information at a given instant.

const (
	StatusUnknown TenderStatus = iota
	StatusOpen
	StatusClosed
	StatusAwarded
)

func (TenderStatus) String

func (s TenderStatus) String() string

type UnsupportedFilterError

type UnsupportedFilterError struct {
	Filter Filter
}

UnsupportedFilterError is returned when a provider is called directly with a criterion it cannot honor.

func (*UnsupportedFilterError) Error

func (e *UnsupportedFilterError) Error() string

type ValidationError

type ValidationError struct {
	Field   string
	Problem string
}

ValidationError identifies one invalid query field.

func (*ValidationError) Error

func (e *ValidationError) Error() string

type Warning

type Warning struct {
	Provider string
	Code     WarningCode
	Message  string
	Err      error
}

Warning describes a non-fatal source-level problem.

type WarningCode

type WarningCode string

WarningCode is a stable machine-readable reason why a federated response is partial or approximate.

const (
	WarningProviderError     WarningCode = "provider_error"
	WarningUnsupportedFilter WarningCode = "unsupported_filter"
	WarningApproximateFilter WarningCode = "approximate_filter"
	WarningTruncated         WarningCode = "truncated"
)

Directories

Path Synopsis
Package beauamp implements muninn.Provider for BEAUAMP (Base Étendue, Améliorée et Unifiée des Annonces des Marchés Publics), published on data.gouv.fr.
Package beauamp implements muninn.Provider for BEAUAMP (Base Étendue, Améliorée et Unifiée des Annonces des Marchés Publics), published on data.gouv.fr.
Package boamp implements muninn.Provider for the BOAMP API (DILA), exposed through an Opendatasoft platform (Explore API v2.1).
Package boamp implements muninn.Provider for the BOAMP API (DILA), exposed through an Opendatasoft platform (Explore API v2.1).
Package consolidate provides a provider-compatible merger.
Package consolidate provides a provider-compatible merger.
Package decp implements muninn.Provider for the DECP dataset (Données Essentielles de la Commande Publique), the mandatory open data of awarded public contracts of 40,000 € HT or more.
Package decp implements muninn.Provider for the DECP dataset (Données Essentielles de la Commande Publique), the mandatory open data of awarded public contracts of 40,000 € HT or more.
internal
httpx
Package httpx provides a shared HTTP retry helper for the providers that hit external, potentially rate-limited government APIs (Opendatasoft, data.gouv.fr).
Package httpx provides a shared HTTP retry helper for the providers that hit external, potentially rate-limited government APIs (Opendatasoft, data.gouv.fr).
ods
Package ods provides the shared plumbing for querying an Opendatasoft Explore API v2.1 dataset.
Package ods provides the shared plumbing for querying an Opendatasoft Explore API v2.1 dataset.
Package retry defines the retry/backoff configuration shared by every muninn provider (boamp, decp, beauamp) for requests against their external, potentially rate-limited government APIs.
Package retry defines the retry/backoff configuration shared by every muninn provider (boamp, decp, beauamp) for requests against their external, potentially rate-limited government APIs.
Package search provides client-side filters over already-fetched []muninn.Tender, complementing the filters each provider pushes server-side (useful when a source does not natively support every criterion, or to refine results after aggregation).
Package search provides client-side filters over already-fetched []muninn.Tender, complementing the filters each provider pushes server-side (useful when a source does not natively support every criterion, or to refine results after aggregation).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL