Anniversaries

Birthday and anniversary SMS keyed to each contact's own date — the platform watches the calendar and sends on the day, with an optional promotional message a few days before.

An anniversary group holds the message, send time and sender; its contacts each carry a name, phone and date. Every day, contacts whose month and day match get the message — year ignored, so one upload works forever. Endpoints live under /api/v1/ with a scoped mbs_ token or JWT; each send is billed as a normal SMS from your unit balance.

Create a group

POST/api/v1/anniversaries

Parameters

FieldTypeRequiredDescription
namestringYesInternal label — "Customer birthdays".
send_time"HH:MM"YesTime of day the messages go out, Africa/Nairobi.
messagestringYesThe day-of message. {{name}} is filled from each contact's stored name.
sender_uuiduuidNoAn approved sender ID; omit for the team default.
promo_enabledbooleanNoAlso send a promotional message N days before the date.
promo_days_beforeint (1–365)NoHow many days before — required when promo_enabled.
promo_messagestringNoThe early message — "{{name}}, treat yourself: 20% off cakes this week!"
enabledbooleanNoDefaults to true.
curl -X POST https://api.mobilesasa.com/api/v1/anniversaries \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer birthdays",
    "send_time": "09:00",
    "message": "Happy birthday {{name}}! 🎉 Enjoy free delivery on anything you order today.",
    "promo_enabled": true,
    "promo_days_before": 3,
    "promo_message": "{{name}}, your birthday is in 3 days — pre-order your cake with 20% off!"
  }'

Add contacts

POST/api/v1/anniversaries/{uuid}/contacts
GET/api/v1/anniversaries/{uuid}/contacts

Contact fields

FieldTypeRequiredDescription
namestringYesFills {{name}} in both messages.
msisdnstringYesAny accepted phone format.
anniversary_dateYYYY-MM-DDYesThe date to celebrate. The year is stored but only month + day drive sending.
curl -X POST https://api.mobilesasa.com/api/v1/anniversaries/9a3c5e77-…/contacts \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "name": "Jane Wanjiku",
        "msisdn": "0712345678",
        "anniversary_date": "1994-07-14"
      },
      {
        "name": "Otieno Odhiambo",
        "msisdn": "0723456789",
        "anniversary_date": "1988-11-02"
      }
    ]
  }'
Response — 200
{
  "success": true,
  "data": { "inserted": 2, "invalid": 0 }
}

Rows can be corrected or removed with PUT/DELETE /anniversaries/{uuid}/contacts/{cuuid}. Contact listings include last_sent_at and last_promo_sent_at so you can audit exactly who got what.

Manage

GET/api/v1/anniversaries
GET/api/v1/anniversaries/{uuid}
PUT/api/v1/anniversaries/{uuid}
POST/api/v1/anniversaries/{uuid}/toggle
DELETE/api/v1/anniversaries/{uuid}
curl -X POST https://api.mobilesasa.com/api/v1/anniversaries/9a3c5e77-…/toggle \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'

Send-once guarantees

Each contact gets at most one day-of message per anniversary — a contact who was already celebrated isn't re-sent for roughly eleven months, so date edits and re-imports can't double-fire. The promo message has its own independent once-per-cycle guard.

Feb 29 and other calendar traps

Month + day matching means a Feb 29 birthday only fires in leap years — store Feb 28 or Mar 1 if the customer prefers an annual message.