Skip to content

Bee Issuance API ​

Credit semillas (community vouchers) to a member from an external system.

Base URL: https://bee.redbroomsoftware.com

Which side of Bee are you on?

This page is for systems that give value to a member — a recycling drop-off point, a sponsor-funded rewards program, any process that decides "this person earned X".

If instead you are a merchant or POS that wants to let a customer pay part of a ticket with vouchers, you want the Bee app page and /api/charge-requests. The two directions are separate endpoints with separate rules.


Before you write code ​

Read what a semilla is first. Two rules from that page decide how this API behaves, and neither is negotiable:

  1. A voucher is a liability of the issuing cell, never of the community administration. When you credit value, you are creating a liability in some cell's name — so the API always requires knowing which cell answers for it.
  2. Minted value cannot be un-minted. There is no reversal endpoint and there will not be one. This is why Idempotency-Key is mandatory rather than recommended.

Authentication ​

http
X-API-Key: <your key>
Content-Type: application/json

Keys live in Bee's database, not in environment variables. Each key carries:

  • a community — the tenant you may write to,
  • a cell scope — the specific cells you may issue on behalf of,
  • two independent revocation switches.

Keys are revoked without a deployment, effective on the next request. Ask the community administration to issue yours; they are created deliberately, one per integrator.

Treat 401 as a loud failure

Do not log a 401 and move on. A previous integration in this ecosystem compared the key against an environment variable while the caller sent a database key: every real request got 401, the sender wrote it to a log nobody read, and the channel was silently dead for months. A 401 here means nothing was credited. Alert on it.


Credit value for recycling ​

http
POST /api/reciclaje

Headers

HeaderRequiredDescription
X-API-KeyyesYour key
Idempotency-KeyyesStable, unique id for the real-world event — the drop-off, the weighing, the transaction in your system. Not a random per-request value.

Body

FieldTypeRequiredDescription
phone_e164stringyesThe member's phone. E.164 (+5215512345678); Mexican legacy forms are normalized for you. This is the identity in Bee — there are no usernames.
amount_centsintegeryesValue to credit, in whole cents. 1 seed = 1 MXN, so 25000 = $250.00 MXN. Never a float.
issuer_cell_idstringonly if your key covers more than one cellThe cell that answers for this liability. With a single-cell key it is inferred.
source_refstringnoYour id for the event. Echoed back; useful for reconciliation.
destinostringnoThe community's budget slug this comes out of. Must be one the community declared.

You send the amount, not the raw measurement. Bee does not convert kilograms to seeds — your conversion model is yours. Bee validates, mints and records.

Example ​

bash
curl -X POST https://bee.redbroomsoftware.com/api/reciclaje \
  -H "X-API-Key: $BEE_API_KEY" \
  -H "Idempotency-Key: dropoff-2026-09-23-00417" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_e164": "+5215512345678",
    "amount_cents": 25000,
    "source_ref": "dropoff-00417"
  }'
json
{
  "ok": true,
  "batchId": "…",
  "amountCents": 25000,
  "memberId": "…",
  "issuerCellId": "…",
  "duplicate": false,
  "expiresAt": "2027-09-23T…",
  "sourceRef": "dropoff-00417"
}

Two response fields that are not decoration ​

duplicate: true means this event was already credited. It is success, not an error — the idempotency worked. Do not retry it and do not add it to the balance a second time.

expiresAt is when this value dies. Vouchers expire (one year by default, anchored to the batch at issuance — a voucher does not get younger because its issuer minted a new batch). Put this date on whatever receipt you hand the person. Promising value without saying when it expires is your app lying on Bee's behalf.


Errors ​

StatuserrorWhat it means and what to do
400idempotency_key_requiredYou omitted the header. Nothing was credited.
400invalid_phoneNot a parseable phone number.
400invalid_amountNot a positive whole number of cents. Floats are rejected.
401unauthorizedKey missing, unknown, inactive or revoked. Deliberately indistinguishable — alert, do not swallow.
403cell_out_of_scopeThat cell is not in your key's scope. You cannot create a liability in another cell's name.
404member_not_foundThe most common one in the field. That phone is not in the community's roster.
409quota_exceededThe issuing cell has no monthly issuance quota (polen) left.
422issuer_cell_requiredYour key covers several cells; say which one. Bee will not choose for you.
422amount_too_largeAbove the per-operation ceiling. A safety belt against a unit mistake — cents read as pesos are 100×.

Handling member_not_found ​

Bee will not create the person for you. Identity is the phone number, and enrolling someone from an integrator's key would turn this endpoint into a public sign-up path.

Show it at the counter as what it is: "this phone isn't registered with the community yet", and let the community enroll them. In practice the beneficiaries are recurring organizations, so this is a one-time step, not daily friction.


How the value behaves once credited ​

Worth knowing, because it shapes what the person can do with it:

  • Vouchers from the cell where you are paying cover 100% of a ticket. Vouchers from other cells are capped — by default 30% of the ticket, aggregated.
  • A cell can be marked exempt from that cap by the community, and a drop-off point normally is: its liability is backed by money sponsors already paid, so its value spends at full weight anywhere in the community while still being recorded as owed by that cell.
  • The acceptance percentage is resolved per issuing cell. It is expected to become richer over time (by member type and by venue type), so do not hard-code 30% anywhere in your integration — read what Bee returns.

Idempotency, concretely ​

See the general idempotency guide. The one rule specific to this endpoint:

Key the request on the real-world event, not the attempt.

A retry after a timeout must carry the same key as the original — the first call may well have succeeded and only the response was lost. Two different keys for one drop-off are two real credits, and there is no way back.

Red Broom Software Ecosystem