Moving from v1

<!-- order: 10 | Connect's catalog and certificate APIs, and the TA API v1.5, on FIP-OS: what stays the same, what changed, and the v2 call for each. -->

FIP-OS answers the older APIs as they answer today, so you can switch to it first and move to v2 later, endpoint by endpoint. Both work on the same records.

Try them in the explorer

Open Reference and explorer and choose v1 compatibility at the top (or open the v1 reference directly). Every v1 endpoint is there with its parameters, examples and errors, what FIP-OS changed, and the v2 call to move to, and you can send it with Try it:

  • Catalog v1, certificates v1 and community: no token needed. Signed in, your token is filled in and the catalog answers as for a token holder.
  • TA API v1.5: needs a TA key's token and your TA-ID. Sign in with /services/oauth2/token as your integration does, or ask an admin for a key's token (Keys and tokens, Use in the explorer) and paste it under Authentication.

The v1 description is at /v1/openapi.json if you want it for your own tools.

The Verified Products catalog API v1

https://api.foodintegrityproject.org/api/v1/catalog/...: the same paths, parameters (including how_sold, cert_group, single_ingredient and context), fields and errors as Connect's, and the same hourly limits (60 an hour without a token, 20,000 with one, with X-RateLimit-* headers).

What changed:

  • Without a token you see only listed products, on every endpoint, a product's and a brand's page included. Listed means what the Program Rules list: verified, or within the grace period after withdrawal or termination. The list is refreshed every 15 minutes.
  • Every product line also has status, certificate_number, valid_to and listed. A client that ignores fields it doesn't know is unaffected.
  • Tokens: Connect's catalog tokens can't be moved (Connect keeps only their hashes). Use a FIP-OS key or token with catalog.read (Keys and tokens). Old tokens keep working on Connect until the cutover date you're told.
v1v2
GET /api/v1/catalog/productsGET /v2/catalog/products (cursor pages, updated_since), plus /v2/catalog/changes and /v2/catalog/export
GET /api/v1/catalog/products/{product_id}GET /v2/catalog/products/{id}
GET /api/v1/catalog/brands, /brands/{brand_id}GET /v2/catalog/brands, /v2/catalog/brands/{number}
GET /api/v1/catalog/categoriesGET /v2/catalog/categories

The certificate (COV) API v1

/api/cov/generate, /api/cov/generate-custom and /api/cov/retrieve, and the old /api/1.1/wf/get_summary_cov, get_custom_cov_summary and get_cov_pdf, with the same parameters (t, key, a, b, p, c, type, title, callback_url) and answers.

What changed:

  • The certificate is ready at once. pdf_url is a lasting link to today's certificate for your request, made from the record each time it's opened, so retrieve always answers complete.
  • p[] is accepted as well as repeated p for a custom list (up to 500 products).
  • callback_url is called once with {cov_id, status: "complete", pdf_url}, and callback_email gets an email with the link. generate-zip answers with a ZIP of each product's certificate, as before.
  • retrieve still answers for certificates Connect made.
  • key: calls without a key keep working until notice is given; then the key becomes your FIP-OS key.

In v2: POST /v2/certificates/pdf, with the certificate.pdf_ready webhook.

The community API

POST /api/v1/community/requests and GET /api/v1/community/activity?upc= answer as Connect's do, with the same fields, texts and limits. Scans are catalog API v1 look-ups made with context=scan, here and on Connect, one per app per 2-second burst. TAs see the demand for their products in GET /v2/demand.

The TA API v1.5

The same paths at this host, https://api.foodintegrityproject.org/services/apexrest/nongmoservices/<resource>, with the same TA-ID header, bodies (bare arrays) and answers ({"status": [...], "objList": [...]}), signed in the same way:

  1. Staff record your integration's Salesforce consumer key and username on your TA's key, and add the public key of the certificate you sign with today.
  2. Change your login host to https://api.foodintegrityproject.org: POST /services/oauth2/token takes the same JWT bearer assertion and answers as Salesforce does, with instance_url set to this host. If your client builds API addresses from instance_url, that's the only change.
  3. An expired token gets Salesforce's INVALID_SESSION_ID (401), so your client signs in again as it does today.

What changed:

  • Your records only, for changes, as before notice for reads: GET /certificate and GET /prospect still answer for every TA until notice is given.
  • Writes are checked as in v2: statuses only to the values Salesforce accepts, your products only, unknown values refused with a message per row instead of being saved as sent.
  • A new facility is registered from the row's facility_name and address (matched first by name and postal code), as before. A brand owned by another company (brand_owner_company_name) is added by staff for now.
  • GET /certificate no longer fails the whole answer when one participant has no license agreement: each line says license_agreement_signed, and certificate_link is a real link.
  • No stack traces in errors.

The v2 call for each v1.5 endpoint:

v1.5v2
POST /product, PATCH /productPUT /v2/products/{ta_product_id}, PATCH /v2/products/{id}
GET /product?ta_product_id= (existence check)GET /v2/products/{id} (404 when it isn't yours or doesn't exist)
POST /verificationPOST /v2/products/{id}/verifications
PATCH /verification with a statusPOST /v2/verifications/{ref}/hold, /release, /withdraw, /terminate, /transfer, /cancel
POST /package, PATCH /packagePOST /v2/products/{id}/packages, PATCH or DELETE /v2/packages/{id}
POST /facility, PATCH /facilityPUT or DELETE /v2/verifications/{ref}/facilities/{facility_id}
POST /client, PATCH /clientPOST /v2/clients, PATCH /v2/clients/{id}, PUT /v2/clients/{id}/contacts/{role}
/coo and /contact (documented, never built)POST /v2/products/{id}/countries-of-origin, PUT /v2/clients/{id}/contacts/{role}
POST /brandPOST /v2/brands
GET /certificateGET /v2/certificates
GET /applicationGET /v2/clients?status=approved&updated_since=
GET /prospect?createdAfter=GET /v2/opportunities?updated_since=, or the opportunity.shared webhook